seitime-frappe/frappe/tests/test_client.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

246 lines
6.9 KiB
Python

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
from unittest.mock import patch
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import get_site_url
class TestClient(IntegrationTestCase):
def test_set_value(self):
todo = frappe.get_doc(doctype="ToDo", description="test").insert()
frappe.set_value("ToDo", todo.name, "description", "test 1")
self.assertEqual(frappe.get_value("ToDo", todo.name, "description"), "test 1")
frappe.set_value("ToDo", todo.name, {"description": "test 2"})
self.assertEqual(frappe.get_value("ToDo", todo.name, "description"), "test 2")
def test_delete(self):
from frappe.client import delete
from frappe.desk.doctype.note.note import Note
note = frappe.get_doc(
doctype="Note",
title=frappe.generate_hash(length=8),
content="test",
seen_by=[{"user": "Administrator"}],
).insert()
child_row_name = note.seen_by[0].name
with patch.object(Note, "save") as save:
delete("Note Seen By", child_row_name)
save.assert_called()
delete("Note", note.name)
self.assertFalse(frappe.db.exists("Note", note.name))
self.assertRaises(frappe.DoesNotExistError, delete, "Note", note.name)
self.assertRaises(frappe.DoesNotExistError, delete, "Note Seen By", child_row_name)
def test_http_valid_method_access(self):
from frappe.client import delete
from frappe.handler import execute_cmd
frappe.set_user("Administrator")
frappe.local.request = frappe._dict()
frappe.local.request.method = "POST"
frappe.local.form_dict = frappe._dict(
{"doc": dict(doctype="ToDo", description="Valid http method"), "cmd": "frappe.client.save"}
)
todo = execute_cmd("frappe.client.save")
self.assertEqual(todo.get("description"), "Valid http method")
delete("ToDo", todo.name)
def test_http_invalid_method_access(self):
from frappe.handler import execute_cmd
frappe.set_user("Administrator")
frappe.local.request = frappe._dict()
frappe.local.request.method = "GET"
frappe.local.form_dict = frappe._dict(
{"doc": dict(doctype="ToDo", description="Invalid http method"), "cmd": "frappe.client.save"}
)
self.assertRaises(frappe.PermissionError, execute_cmd, "frappe.client.save")
def test_run_doc_method(self):
from frappe.handler import execute_cmd
if not frappe.db.exists("Report", "Test Run Doc Method"):
report = frappe.get_doc(
{
"doctype": "Report",
"ref_doctype": "User",
"report_name": "Test Run Doc Method",
"report_type": "Query Report",
"is_standard": "No",
"roles": [{"role": "System Manager"}],
}
).insert()
else:
report = frappe.get_doc("Report", "Test Run Doc Method")
frappe.local.request = frappe._dict()
frappe.local.request.method = "GET"
# Whitelisted, works as expected
frappe.local.form_dict = frappe._dict(
{
"dt": report.doctype,
"dn": report.name,
"method": "toggle_disable",
"cmd": "run_doc_method",
"args": 0,
}
)
execute_cmd(frappe.local.form_dict.cmd)
# Not whitelisted, throws permission error
frappe.local.form_dict = frappe._dict(
{
"dt": report.doctype,
"dn": report.name,
"method": "create_report_py",
"cmd": "run_doc_method",
"args": 0,
}
)
self.assertRaises(frappe.PermissionError, execute_cmd, frappe.local.form_dict.cmd)
def test_array_values_in_request_args(self):
import requests
from frappe.auth import CookieManager, LoginManager
frappe.utils.set_request(path="/")
frappe.local.cookie_manager = CookieManager()
frappe.local.login_manager = LoginManager()
frappe.local.login_manager.login_as("Administrator")
params = {
"doctype": "DocType",
"fields": ["name", "modified"],
"sid": frappe.session.sid,
}
headers = {
"accept": "application/json",
"content-type": "application/json",
}
url = get_site_url(frappe.local.site)
url += "/api/method/frappe.client.get_list"
res = requests.post(url, json=params, headers=headers)
self.assertEqual(res.status_code, 200)
data = res.json()
first_item = data["message"][0]
self.assertTrue("name" in first_item)
self.assertTrue("modified" in first_item)
def test_client_get(self):
from frappe.client import get
todo = frappe.get_doc(doctype="ToDo", description="test").insert()
filters = {"name": todo.name}
filters_json = frappe.as_json(filters)
self.assertEqual(get("ToDo", filters=filters).description, "test")
self.assertEqual(get("ToDo", filters=filters_json).description, "test")
self.assertEqual(get("System Settings", "", "").doctype, "System Settings")
self.assertEqual(get("ToDo", filters={}), get("ToDo", filters="{}"))
todo.delete()
def test_client_insert(self):
from frappe.client import insert
def get_random_title():
return f"test-{frappe.generate_hash()}"
# test insert dict
doc = {"doctype": "Note", "title": get_random_title(), "content": "test"}
note1 = insert(doc)
self.assertTrue(note1)
# test insert json
doc["title"] = get_random_title()
json_doc = frappe.as_json(doc)
note2 = insert(json_doc)
self.assertTrue(note2)
# test insert child doc without parent fields
child_doc = {"doctype": "Note Seen By", "user": "Administrator"}
with self.assertRaises(frappe.ValidationError):
insert(child_doc)
# test insert child doc with parent fields
child_doc = {
"doctype": "Note Seen By",
"user": "Administrator",
"parenttype": "Note",
"parent": note1.name,
"parentfield": "seen_by",
}
note3 = insert(child_doc)
self.assertTrue(note3)
# cleanup
frappe.delete_doc("Note", note1.name)
frappe.delete_doc("Note", note2.name)
def test_client_insert_many(self):
from frappe.client import insert, insert_many
def get_random_title():
return f"test-{frappe.generate_hash(length=5)}"
# insert a (parent) doc
note1 = {"doctype": "Note", "title": get_random_title(), "content": "test"}
note1 = insert(note1)
doc_list = [
{
"doctype": "Note Seen By",
"user": "Administrator",
"parenttype": "Note",
"parent": note1.name,
"parentfield": "seen_by",
},
{
"doctype": "Note Seen By",
"user": "Administrator",
"parenttype": "Note",
"parent": note1.name,
"parentfield": "seen_by",
},
{
"doctype": "Note Seen By",
"user": "Administrator",
"parenttype": "Note",
"parent": note1.name,
"parentfield": "seen_by",
},
{"doctype": "Note", "title": "not-a-random-title", "content": "test"},
{"doctype": "Note", "title": get_random_title(), "content": "test"},
{"doctype": "Note", "title": get_random_title(), "content": "test"},
{"doctype": "Note", "title": "another-note-title", "content": "test"},
]
# insert all docs
docs = insert_many(doc_list)
self.assertEqual(len(docs), 7)
self.assertEqual(frappe.db.get_value("Note", docs[3], "title"), "not-a-random-title")
self.assertEqual(frappe.db.get_value("Note", docs[6], "title"), "another-note-title")
self.assertIn(note1.name, docs)
# cleanup
for doc in docs:
frappe.delete_doc("Note", doc)