blob: 95e56683e1200b2588e7c358f6e851c3c965b434 [file] [log] [blame]
Ankush Menat76dd6e92021-05-23 16:19:48 +05301# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and Contributors
Rushabh Mehta982be9f2017-01-17 17:57:19 +05302# License: GNU General Public License v3. See license.txt
3
Ankush Menat76dd6e92021-05-23 16:19:48 +05304import copy
Ankush Menat06fa35a2021-09-14 20:05:16 +05305import unittest
Ankush Menat76dd6e92021-05-23 16:19:48 +05306from contextlib import contextmanager
Ankush Menat70c203d2021-09-15 19:24:35 +05307from typing import Any, Dict, NewType, Optional
Rushabh Mehta982be9f2017-01-17 17:57:19 +05308
9import frappe
Ankush Menat70c203d2021-09-15 19:24:35 +053010from frappe.core.doctype.report.report import get_report_module_dotted_path
11
12ReportFilters = Dict[str, Any]
13ReportName = NewType("ReportName", str)
Rushabh Mehta982be9f2017-01-17 17:57:19 +053014
Chillar Anand915b3432021-09-02 16:44:59 +053015
Ankush Menat06fa35a2021-09-14 20:05:16 +053016class ERPNextTestCase(unittest.TestCase):
17 """A sane default test class for ERPNext tests."""
18
19 def setUp(self) -> None:
20 frappe.db.commit()
21 return super().setUp()
22
23
24 def tearDown(self) -> None:
25 frappe.db.rollback()
26 return super().tearDown()
27
28
29
Rushabh Mehta982be9f2017-01-17 17:57:19 +053030def create_test_contact_and_address():
Rushabh Mehtaa0c41b72017-01-18 14:14:20 +053031 frappe.db.sql('delete from tabContact')
Nabin Hait1aa8c2e2020-03-26 13:15:31 +053032 frappe.db.sql('delete from `tabContact Email`')
33 frappe.db.sql('delete from `tabContact Phone`')
Rushabh Mehtaa0c41b72017-01-18 14:14:20 +053034 frappe.db.sql('delete from tabAddress')
35 frappe.db.sql('delete from `tabDynamic Link`')
Rushabh Mehta982be9f2017-01-17 17:57:19 +053036
Himanshu25ab1e42019-09-30 10:08:15 +053037 frappe.get_doc({
38 "doctype": "Address",
39 "address_title": "_Test Address for Customer",
40 "address_type": "Office",
41 "address_line1": "Station Road",
42 "city": "_Test City",
43 "state": "Test State",
44 "country": "India",
45 "links": [
46 {
47 "link_doctype": "Customer",
48 "link_name": "_Test Customer"
49 }
50 ]
51 }).insert()
Rushabh Mehtaa0c41b72017-01-18 14:14:20 +053052
Himanshu25ab1e42019-09-30 10:08:15 +053053 contact = frappe.get_doc({
54 "doctype": 'Contact',
55 "first_name": "_Test Contact for _Test Customer",
56 "links": [
57 {
58 "link_doctype": "Customer",
59 "link_name": "_Test Customer"
60 }
61 ]
62 })
63 contact.add_email("test_contact_customer@example.com", is_primary=True)
64 contact.add_phone("+91 0000000000", is_primary_phone=True)
65 contact.insert()
Ankush Menat76dd6e92021-05-23 16:19:48 +053066
67
68@contextmanager
69def change_settings(doctype, settings_dict):
70 """ A context manager to ensure that settings are changed before running
71 function and restored after running it regardless of exceptions occured.
72 This is useful in tests where you want to make changes in a function but
73 don't retain those changes.
74 import and use as decorator to cover full function or using `with` statement.
75
76 example:
77 @change_settings("Stock Settings", {"item_naming_by": "Naming Series"})
78 def test_case(self):
79 ...
80 """
81
82 try:
83 settings = frappe.get_doc(doctype)
84 # remember setting
85 previous_settings = copy.deepcopy(settings_dict)
86 for key in previous_settings:
87 previous_settings[key] = getattr(settings, key)
88
89 # change setting
90 for key, value in settings_dict.items():
91 setattr(settings, key, value)
92 settings.save()
93 yield # yield control to calling function
94
95 finally:
96 # restore settings
97 settings = frappe.get_doc(doctype)
98 for key, value in previous_settings.items():
99 setattr(settings, key, value)
100 settings.save()
Ankush Menat70c203d2021-09-15 19:24:35 +0530101
102
103def execute_script_report(
104 report_name: ReportName,
105 module: str,
106 filters: ReportFilters,
107 default_filters: Optional[ReportFilters] = None,
108 optional_filters: Optional[ReportFilters] = None
109 ):
110 """Util for testing execution of a report with specified filters.
111
112 Tests the execution of report with default_filters + filters.
113 Tests the execution using optional_filters one at a time.
114
115 Args:
116 report_name: Human readable name of report (unscrubbed)
117 module: module to which report belongs to
118 filters: specific values for filters
119 default_filters: default values for filters such as company name.
120 optional_filters: filters which should be tested one at a time in addition to default filters.
121 """
122
123 if default_filters is None:
124 default_filters = {}
125
126 report_execute_fn = frappe.get_attr(get_report_module_dotted_path(module, report_name) + ".execute")
127 report_filters = frappe._dict(default_filters).copy().update(filters)
128
129 report_data = report_execute_fn(report_filters)
130
131 if optional_filters:
132 for key, value in optional_filters.items():
133 filter_with_optional_param = report_filters.copy().update({key: value})
134 report_execute_fn(filter_with_optional_param)
135
136 return report_data