mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-17 10:36:31 +00:00
test: narrow shared fixture hardening (#58581)
This commit is contained in:
@@ -70,8 +70,6 @@ after_install = "erpnext.setup.install.after_install"
|
|||||||
after_app_install = "erpnext.setup.install.after_app_install"
|
after_app_install = "erpnext.setup.install.after_app_install"
|
||||||
after_app_uninstall = "erpnext.setup.install.after_app_uninstall"
|
after_app_uninstall = "erpnext.setup.install.after_app_uninstall"
|
||||||
|
|
||||||
before_tests = "erpnext.tests.utils.bootstrap_test_data"
|
|
||||||
|
|
||||||
boot_session = "erpnext.startup.boot.boot_session"
|
boot_session = "erpnext.startup.boot.boot_session"
|
||||||
notification_config = "erpnext.startup.notifications.get_notification_config"
|
notification_config = "erpnext.startup.notifications.get_notification_config"
|
||||||
get_help_messages = "erpnext.utilities.activation.get_help_messages"
|
get_help_messages = "erpnext.utilities.activation.get_help_messages"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# This file is solely to bootstrap shared test data from CI.
|
# This file is solely to trigger BootStrapTestData from CI
|
||||||
from erpnext.tests.utils import bootstrap_test_data
|
# utils.py module import instantiates BootStrapTestData
|
||||||
|
from erpnext.tests.utils import ERPNextTestSuite
|
||||||
bootstrap_test_data()
|
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# License: GNU General Public License v3. See license.txt
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
from unittest.mock import patch
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
|
|
||||||
from erpnext.tests.utils import (
|
|
||||||
BootstrapTestData,
|
|
||||||
ERPNextTestSuite,
|
|
||||||
change_settings,
|
|
||||||
if_lending_app_installed,
|
|
||||||
if_lending_app_not_installed,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestERPNextTestUtils(ERPNextTestSuite):
|
|
||||||
def test_make_records_reuses_item_price_when_rate_changes(self):
|
|
||||||
fixture = BootstrapTestData.__new__(BootstrapTestData)
|
|
||||||
filters = {"item_code": "_Test Item", "price_list": "_Test Price List Rest of the World"}
|
|
||||||
item_price = frappe.db.get_value("Item Price", filters, "name")
|
|
||||||
self.assertIsNotNone(item_price)
|
|
||||||
frappe.db.set_value("Item Price", item_price, "price_list_rate", 999)
|
|
||||||
|
|
||||||
fixture.make_item_price()
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.count("Item Price", filters), 1)
|
|
||||||
self.assertEqual(frappe.db.get_value("Item Price", filters, "price_list_rate"), 10)
|
|
||||||
|
|
||||||
def test_make_custom_doctype_repairs_each_missing_doctype(self):
|
|
||||||
fixture = BootstrapTestData.__new__(BootstrapTestData)
|
|
||||||
existing_doctypes = {"Shelf", "Rack", "Pallet", "Inv Site"}
|
|
||||||
|
|
||||||
with (
|
|
||||||
patch.object(
|
|
||||||
frappe.db,
|
|
||||||
"exists",
|
|
||||||
side_effect=lambda doctype, name: doctype == "DocType" and name in existing_doctypes,
|
|
||||||
),
|
|
||||||
patch("erpnext.tests.utils.frappe.get_doc") as get_doc,
|
|
||||||
):
|
|
||||||
fixture.make_custom_doctype()
|
|
||||||
|
|
||||||
created_doctypes = [call.args[0]["name"] for call in get_doc.call_args_list]
|
|
||||||
self.assertCountEqual(created_doctypes, ["Store", "Order Assignment"])
|
|
||||||
|
|
||||||
def test_change_settings_restores_values_after_error(self):
|
|
||||||
original = frappe.db.get_single_value("Stock Settings", "auto_indent")
|
|
||||||
changed = 0 if original else 1
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(RuntimeError, "expected failure"):
|
|
||||||
with change_settings("Stock Settings", auto_indent=changed):
|
|
||||||
self.assertEqual(frappe.db.get_single_value("Stock Settings", "auto_indent"), changed)
|
|
||||||
raise RuntimeError("expected failure")
|
|
||||||
|
|
||||||
self.assertEqual(frappe.db.get_single_value("Stock Settings", "auto_indent"), original)
|
|
||||||
|
|
||||||
def test_lending_decorators_preserve_names_and_skip(self):
|
|
||||||
with patch("erpnext.tests.utils.frappe.get_installed_apps", return_value=[]):
|
|
||||||
|
|
||||||
@if_lending_app_installed
|
|
||||||
def requires_lending():
|
|
||||||
return True
|
|
||||||
|
|
||||||
@if_lending_app_not_installed
|
|
||||||
def excludes_lending():
|
|
||||||
return True
|
|
||||||
|
|
||||||
self.assertEqual(requires_lending.__name__, "requires_lending")
|
|
||||||
self.assertEqual(excludes_lending.__name__, "excludes_lending")
|
|
||||||
with self.assertRaises(unittest.SkipTest):
|
|
||||||
requires_lending()
|
|
||||||
self.assertTrue(excludes_lending())
|
|
||||||
|
|
||||||
with patch("erpnext.tests.utils.frappe.get_installed_apps", return_value=["lending"]):
|
|
||||||
|
|
||||||
@if_lending_app_installed
|
|
||||||
def requires_lending():
|
|
||||||
return True
|
|
||||||
|
|
||||||
@if_lending_app_not_installed
|
|
||||||
def excludes_lending():
|
|
||||||
return True
|
|
||||||
|
|
||||||
self.assertTrue(requires_lending())
|
|
||||||
with self.assertRaises(unittest.SkipTest):
|
|
||||||
excludes_lending()
|
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
import copy
|
|
||||||
import unittest
|
import unittest
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from typing import Any, NewType
|
from typing import Any, NewType
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
from frappe import _
|
||||||
from frappe.core.doctype.report.report import get_report_module_dotted_path
|
from frappe.core.doctype.report.report import get_report_module_dotted_path
|
||||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||||
from frappe.tests.utils import load_test_records_for
|
from frappe.tests.utils import load_test_records_for
|
||||||
from frappe.utils import compare, now_datetime, today
|
from frappe.utils import now_datetime, today
|
||||||
|
|
||||||
ReportFilters = dict[str, Any]
|
ReportFilters = dict[str, Any]
|
||||||
ReportName = NewType("ReportName", str)
|
ReportName = NewType("ReportName", str)
|
||||||
_test_data_bootstrapped = False
|
|
||||||
|
|
||||||
|
|
||||||
def execute_script_report(
|
def execute_script_report(
|
||||||
@@ -60,20 +59,30 @@ def execute_script_report(
|
|||||||
|
|
||||||
def if_lending_app_installed(function):
|
def if_lending_app_installed(function):
|
||||||
"""Decorator to check if lending app is installed"""
|
"""Decorator to check if lending app is installed"""
|
||||||
return unittest.skipUnless("lending" in frappe.get_installed_apps(), "lending is not installed")(function)
|
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if "lending" in frappe.get_installed_apps():
|
||||||
|
return function(*args, **kwargs)
|
||||||
|
return
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def if_lending_app_not_installed(function):
|
def if_lending_app_not_installed(function):
|
||||||
"""Decorator to check if lending app is not installed"""
|
"""Decorator to check if lending app is not installed"""
|
||||||
return unittest.skipIf("lending" in frappe.get_installed_apps(), "lending is installed")(function)
|
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
if "lending" not in frappe.get_installed_apps():
|
||||||
|
return function(*args, **kwargs)
|
||||||
|
return
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class BootstrapTestData:
|
class BootStrapTestData:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
lock_name = f"{frappe.local.site}:erpnext-test-data"
|
self.make_presets()
|
||||||
with frappe.db.advisory_lock(lock_name, timeout=300):
|
self.make_master_data()
|
||||||
self.make_presets()
|
|
||||||
self.make_master_data()
|
|
||||||
|
|
||||||
def make_presets(self):
|
def make_presets(self):
|
||||||
from frappe.desk.page.setup_wizard.install_fixtures import update_genders, update_salutations
|
from frappe.desk.page.setup_wizard.install_fixtures import update_genders, update_salutations
|
||||||
@@ -246,56 +255,25 @@ class BootstrapTestData:
|
|||||||
stock_settings.enable_serial_and_batch_no_for_item = 1
|
stock_settings.enable_serial_and_batch_no_for_item = 1
|
||||||
stock_settings.save()
|
stock_settings.save()
|
||||||
|
|
||||||
def make_records(self, key, records, update_fields=()):
|
def make_records(self, key, records):
|
||||||
"""Create shared fixtures once and repair explicitly mutable values."""
|
doctype = records[0].get("doctype")
|
||||||
if not records:
|
|
||||||
return
|
|
||||||
if not key:
|
|
||||||
raise ValueError("make_records expects at least one identity field")
|
|
||||||
|
|
||||||
doctypes = {record.get("doctype") for record in records}
|
def get_filters(record):
|
||||||
if len(doctypes) != 1 or None in doctypes:
|
filters = {}
|
||||||
raise ValueError("make_records expects records for exactly one DocType")
|
for x in key:
|
||||||
|
filters[x] = record.get(x)
|
||||||
|
return filters
|
||||||
|
|
||||||
doctype = doctypes.pop()
|
for x in records:
|
||||||
for record in records:
|
filters = get_filters(x)
|
||||||
filters = {fieldname: record.get(fieldname) for fieldname in key}
|
if not frappe.db.exists(doctype, filters):
|
||||||
if not any(value is not None for value in filters.values()):
|
frappe.get_doc(x).insert()
|
||||||
raise ValueError(f"make_records expects an identity for {doctype}")
|
|
||||||
|
|
||||||
if name := frappe.db.exists(doctype, filters):
|
|
||||||
self._update_fixture_values(doctype, name, record, update_fields)
|
|
||||||
else:
|
|
||||||
frappe.get_doc(record).insert(ignore_if_duplicate=True)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _update_fixture_values(doctype, name, record, update_fields):
|
|
||||||
if not update_fields:
|
|
||||||
return
|
|
||||||
|
|
||||||
doc = frappe.get_doc(doctype, name)
|
|
||||||
changed = False
|
|
||||||
for fieldname in update_fields:
|
|
||||||
if fieldname not in record:
|
|
||||||
continue
|
|
||||||
|
|
||||||
expected = record[fieldname]
|
|
||||||
field = doc.meta.get_field(fieldname)
|
|
||||||
fieldtype = field.fieldtype if field else None
|
|
||||||
if compare(doc.get(fieldname), "=", expected, fieldtype):
|
|
||||||
continue
|
|
||||||
|
|
||||||
doc.set(fieldname, expected)
|
|
||||||
changed = True
|
|
||||||
|
|
||||||
if changed:
|
|
||||||
doc.save(ignore_permissions=True)
|
|
||||||
|
|
||||||
def make_price_list(self):
|
def make_price_list(self):
|
||||||
records = [
|
records = [
|
||||||
{
|
{
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"price_list_name": "Standard Buying",
|
"price_list_name": _("Standard Buying"),
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"buying": 1,
|
"buying": 1,
|
||||||
"selling": 0,
|
"selling": 0,
|
||||||
@@ -303,7 +281,7 @@ class BootstrapTestData:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Price List",
|
"doctype": "Price List",
|
||||||
"price_list_name": "Standard Selling",
|
"price_list_name": _("Standard Selling"),
|
||||||
"enabled": 1,
|
"enabled": 1,
|
||||||
"buying": 0,
|
"buying": 0,
|
||||||
"selling": 1,
|
"selling": 1,
|
||||||
@@ -359,11 +337,7 @@ class BootstrapTestData:
|
|||||||
"selling": 0,
|
"selling": 0,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.make_records(
|
self.make_records(["price_list_name", "enabled", "selling", "buying", "currency"], records)
|
||||||
["price_list_name"],
|
|
||||||
records,
|
|
||||||
update_fields=("enabled", "selling", "buying", "currency", "price_not_uom_dependant"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def make_monthly_distribution(self):
|
def make_monthly_distribution(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -467,7 +441,7 @@ class BootstrapTestData:
|
|||||||
"parent_department": "All Departments",
|
"parent_department": "All Departments",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.make_records(["department_name", "company"], records)
|
self.make_records(["department_name"], records)
|
||||||
|
|
||||||
def make_role(self):
|
def make_role(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -616,7 +590,7 @@ class BootstrapTestData:
|
|||||||
"user_id": "test2@example.com",
|
"user_id": "test2@example.com",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.make_records(["user_id"], records)
|
self.make_records(["first_name"], records)
|
||||||
|
|
||||||
def make_sales_person(self):
|
def make_sales_person(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -752,11 +726,8 @@ class BootstrapTestData:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.make_records(
|
key = ["year_start_date", "year_end_date"]
|
||||||
["year"],
|
self.make_records(key, records)
|
||||||
records,
|
|
||||||
update_fields=("year_start_date", "year_end_date", "is_short_year"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def make_payment_term(self):
|
def make_payment_term(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -1944,7 +1915,7 @@ class BootstrapTestData:
|
|||||||
"company": "_Test Company",
|
"company": "_Test Company",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.make_records(["item_code"], records, update_fields=("item_name",))
|
self.make_records(["item_code", "item_name"], records)
|
||||||
|
|
||||||
def make_product_bundle(self):
|
def make_product_bundle(self):
|
||||||
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
|
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
|
||||||
@@ -2573,7 +2544,7 @@ class BootstrapTestData:
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"doctype": "Item Price",
|
"doctype": "Item Price",
|
||||||
"price_list": "Standard Selling",
|
"price_list": _("Standard Selling"),
|
||||||
"item_code": "Loyal Item",
|
"item_code": "Loyal Item",
|
||||||
"price_list_rate": 10000,
|
"price_list_rate": 10000,
|
||||||
},
|
},
|
||||||
@@ -2584,11 +2555,7 @@ class BootstrapTestData:
|
|||||||
"price_list_rate": 10000,
|
"price_list_rate": 10000,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
self.make_records(
|
self.make_records(["item_code", "price_list", "price_list_rate"], records)
|
||||||
["item_code", "price_list", "customer", "supplier"],
|
|
||||||
records,
|
|
||||||
update_fields=("price_list_rate", "valid_from", "valid_upto", "uom", "packing_unit", "batch_no"),
|
|
||||||
)
|
|
||||||
|
|
||||||
def make_currency_exchange(self):
|
def make_currency_exchange(self):
|
||||||
"""Seed current-dated USD<->INR rates so foreign-currency documents
|
"""Seed current-dated USD<->INR rates so foreign-currency documents
|
||||||
@@ -2620,16 +2587,7 @@ class BootstrapTestData:
|
|||||||
"for_selling": 1,
|
"for_selling": 1,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
identity_fields = ("from_currency", "to_currency", "for_buying", "for_selling")
|
self.make_records(["from_currency", "to_currency", "date", "for_buying", "for_selling"], records)
|
||||||
for record in records:
|
|
||||||
filters = {fieldname: record.get(fieldname) for fieldname in identity_fields}
|
|
||||||
name = frappe.db.get_value("Currency Exchange", filters, "name", order_by="date desc")
|
|
||||||
if name:
|
|
||||||
self._update_fixture_values(
|
|
||||||
"Currency Exchange", name, record, update_fields=("date", "exchange_rate")
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
frappe.get_doc(record).insert(ignore_if_duplicate=True)
|
|
||||||
|
|
||||||
def make_operation(self):
|
def make_operation(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -2755,87 +2713,160 @@ class BootstrapTestData:
|
|||||||
self.make_records(["finance_book_name"], records)
|
self.make_records(["finance_book_name"], records)
|
||||||
|
|
||||||
def make_custom_doctype(self):
|
def make_custom_doctype(self):
|
||||||
for doctype, fieldname, label in (
|
if not frappe.db.exists("DocType", "Shelf"):
|
||||||
("Shelf", "shelf_name", "Shelf Name"),
|
frappe.get_doc(
|
||||||
("Rack", "rack_name", "Rack Name"),
|
{
|
||||||
("Pallet", "pallet_name", "Pallet Name"),
|
"doctype": "DocType",
|
||||||
("Inv Site", "site_name", "Site Name"),
|
"name": "Shelf",
|
||||||
("Store", "store_name", "Store Name"),
|
"module": "Stock",
|
||||||
):
|
"custom": 1,
|
||||||
self._make_simple_custom_doctype(doctype, fieldname, label)
|
"naming_rule": "By fieldname",
|
||||||
|
"autoname": "field:shelf_name",
|
||||||
|
"fields": [{"label": "Shelf Name", "fieldname": "shelf_name", "fieldtype": "Data"}],
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"role": "System Manager",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
self._make_order_assignment_doctype()
|
if not frappe.db.exists("DocType", "Rack"):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "DocType",
|
||||||
|
"name": "Rack",
|
||||||
|
"module": "Stock",
|
||||||
|
"custom": 1,
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"autoname": "field:rack_name",
|
||||||
|
"fields": [{"label": "Rack Name", "fieldname": "rack_name", "fieldtype": "Data"}],
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"role": "System Manager",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
@staticmethod
|
if not frappe.db.exists("DocType", "Pallet"):
|
||||||
def _make_simple_custom_doctype(doctype, fieldname, label):
|
frappe.get_doc(
|
||||||
if frappe.db.exists("DocType", doctype):
|
{
|
||||||
return
|
"doctype": "DocType",
|
||||||
|
"name": "Pallet",
|
||||||
|
"module": "Stock",
|
||||||
|
"custom": 1,
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"autoname": "field:pallet_name",
|
||||||
|
"fields": [{"label": "Pallet Name", "fieldname": "pallet_name", "fieldtype": "Data"}],
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"role": "System Manager",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
frappe.get_doc(
|
if not frappe.db.exists("DocType", "Inv Site"):
|
||||||
{
|
frappe.get_doc(
|
||||||
"doctype": "DocType",
|
{
|
||||||
"name": doctype,
|
"doctype": "DocType",
|
||||||
"module": "Stock",
|
"name": "Inv Site",
|
||||||
"custom": 1,
|
"module": "Stock",
|
||||||
"naming_rule": "By fieldname",
|
"custom": 1,
|
||||||
"autoname": f"field:{fieldname}",
|
"naming_rule": "By fieldname",
|
||||||
"fields": [{"label": label, "fieldname": fieldname, "fieldtype": "Data"}],
|
"autoname": "field:site_name",
|
||||||
"permissions": [
|
"fields": [{"label": "Site Name", "fieldname": "site_name", "fieldtype": "Data"}],
|
||||||
{
|
"permissions": [
|
||||||
"role": "System Manager",
|
{
|
||||||
"permlevel": 0,
|
"role": "System Manager",
|
||||||
"read": 1,
|
"permlevel": 0,
|
||||||
"write": 1,
|
"read": 1,
|
||||||
"create": 1,
|
"write": 1,
|
||||||
"delete": 1,
|
"create": 1,
|
||||||
}
|
"delete": 1,
|
||||||
],
|
}
|
||||||
}
|
],
|
||||||
).insert(ignore_permissions=True, ignore_if_duplicate=True)
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
@staticmethod
|
if not frappe.db.exists("DocType", "Store"):
|
||||||
def _make_order_assignment_doctype():
|
frappe.get_doc(
|
||||||
if frappe.db.exists("DocType", "Order Assignment"):
|
{
|
||||||
return
|
"doctype": "DocType",
|
||||||
|
"name": "Store",
|
||||||
|
"module": "Stock",
|
||||||
|
"custom": 1,
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
|
"autoname": "field:store_name",
|
||||||
|
"fields": [{"label": "Store Name", "fieldname": "store_name", "fieldtype": "Data"}],
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"role": "System Manager",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read": 1,
|
||||||
|
"write": 1,
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
|
||||||
frappe.get_doc(
|
if not frappe.db.exists("DocType", "Order Assignment"):
|
||||||
{
|
frappe.get_doc(
|
||||||
"doctype": "DocType",
|
{
|
||||||
"name": "Order Assignment",
|
"doctype": "DocType",
|
||||||
"module": "Buying",
|
"name": "Order Assignment",
|
||||||
"custom": 1,
|
"module": "Buying",
|
||||||
"autoname": "field:po",
|
"custom": 1,
|
||||||
"fields": [
|
"autoname": "field:po",
|
||||||
{
|
"fields": [
|
||||||
"label": "PO",
|
{
|
||||||
"fieldname": "po",
|
"label": "PO",
|
||||||
"fieldtype": "Link",
|
"fieldname": "po",
|
||||||
"options": "Purchase Order",
|
"fieldtype": "Link",
|
||||||
},
|
"options": "Purchase Order",
|
||||||
{
|
},
|
||||||
"label": "Supplier",
|
{
|
||||||
"fieldname": "supplier",
|
"label": "Supplier",
|
||||||
"fieldtype": "Data",
|
"fieldname": "supplier",
|
||||||
"fetch_from": "po.supplier",
|
"fieldtype": "Data",
|
||||||
},
|
"fetch_from": "po.supplier",
|
||||||
],
|
},
|
||||||
"permissions": [
|
],
|
||||||
{
|
"permissions": [
|
||||||
"create": 1,
|
{
|
||||||
"delete": 1,
|
"create": 1,
|
||||||
"email": 1,
|
"delete": 1,
|
||||||
"export": 1,
|
"email": 1,
|
||||||
"print": 1,
|
"export": 1,
|
||||||
"read": 1,
|
"print": 1,
|
||||||
"report": 1,
|
"read": 1,
|
||||||
"role": "System Manager",
|
"report": 1,
|
||||||
"share": 1,
|
"role": "System Manager",
|
||||||
"write": 1,
|
"share": 1,
|
||||||
},
|
"write": 1,
|
||||||
{"read": 1, "role": "Supplier"},
|
},
|
||||||
],
|
{"read": 1, "role": "Supplier"},
|
||||||
}
|
],
|
||||||
).insert(ignore_permissions=True, ignore_if_duplicate=True)
|
}
|
||||||
|
).insert(ignore_if_duplicate=True)
|
||||||
|
|
||||||
def make_address(self):
|
def make_address(self):
|
||||||
records = [
|
records = [
|
||||||
@@ -3015,21 +3046,7 @@ class BootstrapTestData:
|
|||||||
self.make_records(["store_name"], records)
|
self.make_records(["store_name"], records)
|
||||||
|
|
||||||
|
|
||||||
# Keep the old spelling for test helpers in downstream apps.
|
BootStrapTestData()
|
||||||
BootStrapTestData = BootstrapTestData
|
|
||||||
|
|
||||||
|
|
||||||
def bootstrap_test_data():
|
|
||||||
global _test_data_bootstrapped
|
|
||||||
if _test_data_bootstrapped:
|
|
||||||
return
|
|
||||||
|
|
||||||
BootstrapTestData()
|
|
||||||
_test_data_bootstrapped = True
|
|
||||||
|
|
||||||
|
|
||||||
# Downstream apps create their fixtures while importing this module.
|
|
||||||
bootstrap_test_data()
|
|
||||||
|
|
||||||
|
|
||||||
class ERPNextTestSuite(unittest.TestCase):
|
class ERPNextTestSuite(unittest.TestCase):
|
||||||
@@ -3043,7 +3060,6 @@ class ERPNextTestSuite(unittest.TestCase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
bootstrap_test_data()
|
|
||||||
cls.globalTestRecords = {}
|
cls.globalTestRecords = {}
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@@ -3070,21 +3086,24 @@ class ERPNextTestSuite(unittest.TestCase):
|
|||||||
@ERPNextTestSuite.registerAs(staticmethod)
|
@ERPNextTestSuite.registerAs(staticmethod)
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def change_settings(doctype, settings_dict=None, /, **settings) -> None:
|
def change_settings(doctype, settings_dict=None, /, **settings) -> None:
|
||||||
"""Temporarily change fields in a settings DocType."""
|
"""Temporarily: change settings in a settings doctype."""
|
||||||
|
import copy
|
||||||
|
|
||||||
if settings_dict is None:
|
if settings_dict is None:
|
||||||
settings_dict = settings
|
settings_dict = settings
|
||||||
|
|
||||||
settings_doc = frappe.get_doc(doctype)
|
settings = frappe.get_doc(doctype)
|
||||||
previous_settings = {key: copy.deepcopy(settings_doc.get(key)) for key in settings_dict}
|
previous_settings = copy.deepcopy(settings_dict)
|
||||||
|
for key in previous_settings:
|
||||||
|
previous_settings[key] = getattr(settings, key)
|
||||||
|
|
||||||
for key, value in settings_dict.items():
|
for key, value in settings_dict.items():
|
||||||
settings_doc.set(key, value)
|
setattr(settings, key, value)
|
||||||
settings_doc.save(ignore_permissions=True)
|
settings.save(ignore_permissions=True)
|
||||||
|
|
||||||
try:
|
yield
|
||||||
yield
|
|
||||||
finally:
|
settings = frappe.get_doc(doctype)
|
||||||
settings_doc = frappe.get_doc(doctype)
|
for key, value in previous_settings.items():
|
||||||
for key, value in previous_settings.items():
|
setattr(settings, key, value)
|
||||||
settings_doc.set(key, value)
|
settings.save(ignore_permissions=True)
|
||||||
settings_doc.save(ignore_permissions=True)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user