Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
86 lines
3.3 KiB
Python
86 lines
3.3 KiB
Python
# Copyright (c) 2026, Frappe Technologies Pvt. Ltd. and contributors
|
|
# For license information, please see license.txt
|
|
|
|
import sys
|
|
from types import ModuleType
|
|
from unittest.mock import patch
|
|
|
|
import frappe
|
|
from frappe.tests.utils import FrappeTestCase
|
|
|
|
from crm.www.crm import get_boot, get_state_options
|
|
|
|
|
|
def _fake_india_compliance(states: dict) -> dict:
|
|
"""Build a fake `india_compliance.gst_india.constants` module tree for sys.modules.
|
|
|
|
`from india_compliance.gst_india.constants import INDIAN_STATES` imports each parent
|
|
package, so all three levels must be present.
|
|
"""
|
|
root = ModuleType("india_compliance")
|
|
gst = ModuleType("india_compliance.gst_india")
|
|
constants = ModuleType("india_compliance.gst_india.constants")
|
|
constants.INDIAN_STATES = states
|
|
return {
|
|
"india_compliance": root,
|
|
"india_compliance.gst_india": gst,
|
|
"india_compliance.gst_india.constants": constants,
|
|
}
|
|
|
|
|
|
class TestGetStateOptions(FrappeTestCase):
|
|
def test_returns_a_dict(self):
|
|
# Never raises; always a dict regardless of what's installed.
|
|
self.assertIsInstance(get_state_options(), dict)
|
|
|
|
def test_empty_without_india_compliance(self):
|
|
with patch("crm.www.crm.get_installed_apps", return_value=["frappe", "crm"]):
|
|
self.assertEqual(get_state_options(), {})
|
|
|
|
def test_resilient_when_get_installed_apps_raises(self):
|
|
# The v15 boot-context concern: get_installed_apps blowing up must NOT break boot.
|
|
with patch("crm.www.crm.get_installed_apps", side_effect=Exception("boot context")):
|
|
self.assertEqual(get_state_options(), {})
|
|
|
|
def test_resilient_when_import_fails(self):
|
|
# App reported installed but the constant import fails (e.g. version mismatch).
|
|
# Inject a constants module lacking INDIAN_STATES so the import fails deterministically,
|
|
# regardless of whether india_compliance is actually importable in this environment.
|
|
broken = _fake_india_compliance({})
|
|
del broken["india_compliance.gst_india.constants"].INDIAN_STATES
|
|
with (
|
|
patch("crm.www.crm.get_installed_apps", return_value=["frappe", "crm", "india_compliance"]),
|
|
patch.dict(sys.modules, broken),
|
|
):
|
|
self.assertEqual(get_state_options(), {})
|
|
|
|
def test_returns_states_when_app_installed(self):
|
|
states = {"Goa": "30", "Kerala": "32", "Punjab": "03"}
|
|
with (
|
|
patch(
|
|
"crm.www.crm.get_installed_apps",
|
|
return_value=["frappe", "crm", "india_compliance"],
|
|
),
|
|
patch.dict(sys.modules, _fake_india_compliance(states)),
|
|
):
|
|
result = get_state_options()
|
|
self.assertEqual(list(result.keys()), ["India"])
|
|
self.assertEqual(result["India"], ["Goa", "Kerala", "Punjab"])
|
|
|
|
|
|
class TestGetBoot(FrappeTestCase):
|
|
def test_boot_includes_state_options_and_does_not_raise(self):
|
|
boot = get_boot()
|
|
self.assertIn("state_options", boot)
|
|
self.assertIsInstance(boot["state_options"], dict)
|
|
|
|
def test_boot_degrades_when_state_lookup_fails(self):
|
|
# The v15 boot-context concern: if the state lookup misbehaves, get_boot must still
|
|
# succeed and state_options must be an empty map (never break page load). Patch only
|
|
# the binding used by get_state_options — patching frappe.get_installed_apps globally
|
|
# would break unrelated earlier boot steps (get_translated_doctypes resolves hooks via
|
|
# get_installed_apps), which is what made this test fail in CI.
|
|
with patch("crm.www.crm.get_installed_apps", side_effect=Exception("boot context")):
|
|
boot = get_boot()
|
|
self.assertEqual(boot["state_options"], {})
|