seitime-frappe/frappe/tests/test_linked_with.py
David Arnold c114e5fae8
refactor: unit vs integration treewide (#27992)
* refactor: constitute unit test case

* fix: docs and type hints

* refactor: mark presumed integration test cases explicitly

At time of writing, we now have at least two base test classes:

- frappe.tests.UnitTestCase
- frappe.tests.IntegrationTestCase

They load in their perspective priority queue during execution.

Probably more to come for more efficient queing and scheduling.

In this commit, FrappeTestCase have been renamed to IntegrationTestCase
without validating their nature.

* feat: Move test-related functions from test_runner.py to tests/utils.py

* refactor: add bare UnitTestCase to all doctype tests

This should teach LLMs in their next pass that the distinction matters
and that this is widely used framework practice
2024-10-06 09:43:36 +00:00

187 lines
5.3 KiB
Python

import random
import string
import frappe
from frappe.core.doctype.doctype.test_doctype import new_doctype
from frappe.database import savepoint
from frappe.desk.form import linked_with
from frappe.tests import IntegrationTestCase
class TestLinkedWith(IntegrationTestCase):
def setUp(self):
parent_doctype = new_doctype("Parent DocType")
parent_doctype.is_submittable = 1
parent_doctype.insert()
child_doctype1 = new_doctype(
"Child DocType1",
fields=[
{
"label": "Parent DocType",
"fieldname": "parent_doctype",
"fieldtype": "Link",
"options": "Parent DocType",
},
{
"label": "Reference field",
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"options": "reference_doctype",
},
{
"label": "Reference Doctype",
"fieldname": "reference_doctype",
"fieldtype": "Link",
"options": "DocType",
},
],
unique=0,
)
child_doctype1.is_submittable = 1
child_doctype1.insert()
child_doctype2 = new_doctype(
"Child DocType2",
fields=[
{
"label": "Parent DocType",
"fieldname": "parent_doctype",
"fieldtype": "Link",
"options": "Parent DocType",
},
{
"label": "Child DocType1",
"fieldname": "child_doctype1",
"fieldtype": "Link",
"options": "Child DocType1",
},
],
unique=0,
)
child_doctype2.is_submittable = 1
child_doctype2.insert()
def tearDown(self):
for doctype in ["Parent DocType", "Child DocType1", "Child DocType2"]:
frappe.delete_doc("DocType", doctype)
frappe.db.commit()
def test_get_doctype_references_by_link_field(self):
references = linked_with.get_references_across_doctypes_by_link_field(to_doctypes=["Parent DocType"])
self.assertEqual(len(references["Parent DocType"]), 3)
self.assertIn(
{"doctype": "Child DocType1", "fieldname": "parent_doctype"}, references["Parent DocType"]
)
self.assertIn(
{"doctype": "Child DocType2", "fieldname": "parent_doctype"}, references["Parent DocType"]
)
references = linked_with.get_references_across_doctypes_by_link_field(to_doctypes=["Child DocType1"])
self.assertEqual(len(references["Child DocType1"]), 2)
self.assertIn(
{"doctype": "Child DocType2", "fieldname": "child_doctype1"}, references["Child DocType1"]
)
references = linked_with.get_references_across_doctypes_by_link_field(
to_doctypes=["Child DocType1", "Parent DocType"], limit_link_doctypes=["Child DocType1"]
)
self.assertEqual(len(references["Child DocType1"]), 1)
self.assertEqual(len(references["Parent DocType"]), 1)
self.assertIn(
{"doctype": "Child DocType1", "fieldname": "parent_doctype"}, references["Parent DocType"]
)
def test_get_doctype_references_by_dlink_field(self):
references = linked_with.get_references_across_doctypes_by_dynamic_link_field(
to_doctypes=["Parent DocType"],
limit_link_doctypes=["Parent DocType", "Child DocType1", "Child DocType2"],
)
self.assertFalse(references)
parent_record = frappe.get_doc({"doctype": "Parent DocType"}).insert()
child_record = frappe.get_doc(
{
"doctype": "Child DocType1",
"reference_doctype": "Parent DocType",
"reference_name": parent_record.name,
}
).insert()
references = linked_with.get_references_across_doctypes_by_dynamic_link_field(
to_doctypes=["Parent DocType"],
limit_link_doctypes=["Parent DocType", "Child DocType1", "Child DocType2"],
)
self.assertEqual(len(references["Parent DocType"]), 1)
self.assertEqual(references["Parent DocType"][0]["doctype"], "Child DocType1")
self.assertEqual(references["Parent DocType"][0]["doctype_fieldname"], "reference_doctype")
child_record.delete()
parent_record.delete()
def test_get_submitted_linked_docs(self):
parent_record = frappe.get_doc({"doctype": "Parent DocType"}).insert()
child_record = frappe.get_doc(
{
"doctype": "Child DocType1",
"reference_doctype": "Parent DocType",
"reference_name": parent_record.name,
"docstatus": 1,
}
).insert()
linked_docs = linked_with.get_submitted_linked_docs(parent_record.doctype, parent_record.name)["docs"]
self.assertIn(child_record.name, linked_docs[0]["name"])
child_record.cancel()
child_record.delete()
parent_record.delete()
def test_check_delete_integrity(self):
"""Don't allow deleting cancelled document if amendment exists"""
doc = frappe.get_doc({"doctype": "Parent DocType"}).insert()
doc.submit()
doc.cancel()
amendment = frappe.copy_doc(doc)
amendment.amended_from = doc.name
amendment.docstatus = 0
amendment.insert()
amendment.submit()
self.assertRaises(frappe.LinkExistsError, doc.delete)
def test_reserved_keywords(self):
dt_name = "Test " + "".join(random.sample(string.ascii_lowercase, 10))
new_doctype(
dt_name,
fields=[
{
"fieldname": "from",
"fieldtype": "Link",
"options": "DocType",
},
{
"fieldname": "order",
"fieldtype": "Dynamic Link",
"options": "from",
},
],
is_submittable=True,
).insert()
linked_doc = frappe.new_doc(dt_name).insert().submit()
second_doc = (
frappe.new_doc(dt_name, **{"from": linked_doc.doctype, "order": linked_doc.name})
.insert()
.submit()
)
with savepoint(frappe.LinkExistsError):
linked_doc.cancel() and self.fail("Cancellation shouldn't have worked")
second_doc.cancel()
linked_doc.reload().cancel()