-
Notifications
You must be signed in to change notification settings - Fork 3
test: add tests/ folders to 5 modules missing CI coverage (#1040) #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
emjay0921
wants to merge
3
commits into
19.0
Choose a base branch
from
fix/1040-add-missing-tests
base: 19.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
99ab606
test: add tests/ folders to 5 modules missing CI coverage (#1040)
emjay0921 371751b
chore(spp_farmer_registry_dashboard): drop tests/ — blocked by missin…
emjay0921 ce53fd4
test(spp_hide_menus_base): cover IrModuleModule.hide_menus() catalog …
emjay0921 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| from . import test_spp_drims_sl |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| """Install / data-load sanity tests for spp_drims_sl. | ||
|
|
||
| This is a data-only module (Sri Lanka locale configuration for DRIMS) — | ||
| it ships seed records but no Python models or methods. The tests below | ||
| exercise the install path so CI's per-module coverage matrix has | ||
| something to report against, and assert that the headline data records | ||
| the rest of the module relies on are actually present after install. | ||
| """ | ||
|
|
||
| from odoo.tests import TransactionCase, tagged | ||
|
|
||
|
|
||
| @tagged("post_install", "-at_install") | ||
| class TestSppDrimsSl(TransactionCase): | ||
| """Spot-check that the seed data declared in __manifest__.py loaded.""" | ||
|
|
||
| def test_module_is_installed(self): | ||
| module = self.env["ir.module.module"].search([("name", "=", "spp_drims_sl")], limit=1) | ||
| self.assertTrue(module, "spp_drims_sl module not registered") | ||
| self.assertEqual( | ||
| module.state, | ||
| "installed", | ||
| f"spp_drims_sl expected 'installed', got {module.state}", | ||
| ) | ||
|
|
||
| def test_hazard_category_seed_loaded(self): | ||
| """data/hazard_categories.xml declares at least one category.""" | ||
| category = self.env.ref("spp_drims_sl.category_natural", raise_if_not_found=False) | ||
| self.assertTrue( | ||
| category, | ||
| "spp_drims_sl.category_natural missing — hazard_categories.xml didn't load", | ||
| ) | ||
|
|
||
| def test_sl_currency_company_config(self): | ||
| """data/company_config.xml activates LKR for the locale.""" | ||
| currency = self.env.ref("base.LKR", raise_if_not_found=False) | ||
| self.assertTrue(currency, "base.LKR currency missing") | ||
| self.assertTrue( | ||
| currency.active, | ||
| "LKR currency expected to be active after spp_drims_sl install", | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| from . import test_hide_menu |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,175 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| """Tests for spp_hide_menus_base — hide/show menu visibility logic. | ||
|
|
||
| The module patches ``ir.module.module`` to hide a curated list of stock | ||
| Odoo menus (Project, Calendar, Stock, ...) from the OpenSPP user group | ||
| when an install/upgrade completes. The tests exercise the ``hide_menu`` | ||
| and ``show_menu`` round-trip on ``spp.hide.menu`` directly so we cover | ||
| the model's state transition without depending on a real "Apps install" | ||
| flow. | ||
| """ | ||
|
|
||
| from odoo.tests import TransactionCase, tagged | ||
|
|
||
|
|
||
| @tagged("post_install", "-at_install") | ||
| class TestSppHideMenu(TransactionCase): | ||
| """Exercise the hide / show round-trip on a sample menu.""" | ||
|
|
||
| @classmethod | ||
| def setUpClass(cls): | ||
| super().setUpClass() | ||
| # Pick any existing menu we can safely toggle in a test transaction. | ||
| cls.menu = cls.env["ir.ui.menu"].search([], limit=1) | ||
| if not cls.menu: | ||
| raise AssertionError("No ir.ui.menu records found to test against") | ||
|
|
||
| def test_module_is_installed(self): | ||
| module = self.env["ir.module.module"].search([("name", "=", "spp_hide_menus_base")], limit=1) | ||
| self.assertEqual(module.state, "installed") | ||
|
|
||
| def test_group_hide_menus_user_seed(self): | ||
| """security/groups.xml must declare the hide-menus-user group.""" | ||
| group = self.env.ref("spp_hide_menus_base.group_hide_menus_user", raise_if_not_found=False) | ||
| self.assertTrue( | ||
| group, | ||
| "group_hide_menus_user must exist — hide_menu() falls back on it", | ||
| ) | ||
|
|
||
| def test_hide_menu_transition(self): | ||
| """hide_menu() flips state show → hide and snapshots original groups.""" | ||
| original_groups = self.env["ir.ui.menu"].browse(self.menu.id).group_ids | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| record = self.env["spp.hide.menu"].create({"menu_id": self.menu.id, "xml_id": "test.hide_menu_target"}) | ||
| self.assertEqual(record.state, "show") | ||
|
|
||
| record.hide_menu() | ||
|
|
||
| self.assertEqual(record.state, "hide") | ||
| # Original groups were saved on the record so show_menu can restore them. | ||
| self.assertEqual(record.default_group_ids, original_groups) | ||
|
|
||
| def test_show_menu_restores_original_groups(self): | ||
| """show_menu() restores the snapshot taken at hide time.""" | ||
| original_groups = self.env["ir.ui.menu"].browse(self.menu.id).group_ids | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| record = self.env["spp.hide.menu"].create({"menu_id": self.menu.id, "xml_id": "test.hide_menu_target"}) | ||
| record.hide_menu() | ||
| # Menu is now restricted to the hide-menus-user group only. | ||
| self.assertNotEqual(self.menu.group_ids, original_groups) | ||
|
|
||
| record.show_menu() | ||
| self.assertEqual(record.state, "show") | ||
| self.assertEqual(self.menu.group_ids, original_groups) | ||
|
|
||
| def test_hide_menu_noop_when_already_hidden(self): | ||
| """Calling hide_menu twice doesn't change state or groups again.""" | ||
| record = self.env["spp.hide.menu"].create({"menu_id": self.menu.id, "xml_id": "test.hide_menu_target"}) | ||
| record.hide_menu() | ||
| snapshot = record.default_group_ids | ||
| record.hide_menu() # second call — guarded by state == "show" | ||
| self.assertEqual(record.state, "hide") | ||
| # Original snapshot must not be overwritten by the second call. | ||
| self.assertEqual(record.default_group_ids, snapshot) | ||
|
|
||
| def test_menu_app_catalog_is_well_formed(self): | ||
| """ir.module.module.MENU_APP entries must point to a menu xml_id.""" | ||
| IrModuleModule = self.env["ir.module.module"] | ||
| for module_name, info in IrModuleModule.MENU_APP.items(): | ||
| self.assertIn( | ||
| "menu_xml_id", | ||
| info, | ||
| f"MENU_APP[{module_name!r}] missing required 'menu_xml_id'", | ||
| ) | ||
| self.assertTrue( | ||
| info["menu_xml_id"], | ||
| f"MENU_APP[{module_name!r}].menu_xml_id is empty", | ||
| ) | ||
|
|
||
| def test_hide_menus_processes_catalog(self): | ||
| """``ir.module.module.hide_menus()`` walks MENU_APP and creates a | ||
| ``spp.hide.menu`` record (state=hide) for every entry whose menu | ||
| xml_id resolves in the current DB. | ||
| """ | ||
| IrModuleModule = self.env["ir.module.module"] | ||
| HideMenu = self.env["spp.hide.menu"] | ||
|
|
||
| # Figure out which catalog entries are actually resolvable here — | ||
| # most stock Odoo modules in MENU_APP (mail, contacts, ...) are | ||
| # present in any test DB, but a few (mass_mailing, survey, ...) | ||
| # may not be installed. | ||
| resolvable = [] | ||
| for module_name, info in IrModuleModule.MENU_APP.items(): | ||
| menu = self.env.ref(info["menu_xml_id"], raise_if_not_found=False) | ||
| module = IrModuleModule.search([("name", "=", module_name)], limit=1) | ||
| if menu and module: | ||
| resolvable.append((module_name, menu.id)) | ||
|
|
||
| if not resolvable: | ||
| self.skipTest("No MENU_APP entries are resolvable in this test DB") | ||
|
|
||
| # Wipe any pre-existing spp.hide.menu so the test's assertions are | ||
| # clearly about hide_menus()'s effect, not the install hook. | ||
| HideMenu.search([]).unlink() | ||
|
|
||
| IrModuleModule.hide_menus() | ||
|
|
||
| for module_name, menu_id in resolvable: | ||
| record = HideMenu.search([("menu_id", "=", menu_id)], limit=1) | ||
| self.assertTrue( | ||
| record, | ||
| f"hide_menus() didn't create a spp.hide.menu for {module_name!r}", | ||
| ) | ||
| self.assertEqual( | ||
| record.state, | ||
| "hide", | ||
| f"spp.hide.menu for {module_name!r} expected state=hide, got {record.state}", | ||
| ) | ||
|
|
||
| def test_hide_menus_is_idempotent(self): | ||
| """Calling hide_menus() twice doesn't double-hide already-hidden menus. | ||
|
|
||
| After the first pass every resolvable entry is in state=hide. A | ||
| second pass must leave them in state=hide (the inner guard | ||
| ``elif hidden_menus.state == "show"`` skips them). | ||
| """ | ||
| IrModuleModule = self.env["ir.module.module"] | ||
| HideMenu = self.env["spp.hide.menu"] | ||
|
|
||
| HideMenu.search([]).unlink() | ||
| IrModuleModule.hide_menus() | ||
| after_first = HideMenu.search([]) | ||
| self.assertTrue( | ||
| after_first, | ||
| "hide_menus() didn't create any records — nothing to check idempotency against", | ||
| ) | ||
|
|
||
| IrModuleModule.hide_menus() | ||
| after_second = HideMenu.search([]) | ||
| # No duplicates created and every record stayed in state=hide. | ||
| self.assertEqual(set(after_first.ids), set(after_second.ids)) | ||
| for record in after_second: | ||
| self.assertEqual(record.state, "hide") | ||
|
|
||
| def test_hide_menus_skips_unknown_modules(self): | ||
| """An ir.module.module record whose name isn't in MENU_APP must be | ||
| ignored by hide_menus() — no spp.hide.menu record is created for it. | ||
| """ | ||
| IrModuleModule = self.env["ir.module.module"] | ||
| HideMenu = self.env["spp.hide.menu"] | ||
|
|
||
| # ``base`` is always installed and is NOT in MENU_APP. | ||
| self.assertNotIn("base", IrModuleModule.MENU_APP) | ||
|
|
||
| before = HideMenu.search([]).ids | ||
| IrModuleModule.hide_menus() | ||
| after = HideMenu.search([]).ids | ||
|
|
||
| # Whatever new records appeared, none should belong to the ``base`` menu. | ||
| new_ids = set(after) - set(before) | ||
| for record in HideMenu.browse(list(new_ids)): | ||
| self.assertNotEqual( | ||
| record.menu_id.id, | ||
| self.env.ref("base.menu_administration").id | ||
| if self.env.ref("base.menu_administration", raise_if_not_found=False) | ||
| else 0, | ||
| "hide_menus() shouldn't touch base.menu_administration", | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| from . import test_spp_indicator_studio |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| """Install / view-load sanity tests for spp_indicator_studio. | ||
|
|
||
| This is a UI-bridge module — it ships act_window actions and form/list | ||
| views for ``spp.indicator`` and ``spp.indicator.category`` but no Python | ||
| models or methods of its own. The tests verify the install path and that | ||
| the headline view + action records loaded. | ||
| """ | ||
|
|
||
| from odoo.tests import TransactionCase, tagged | ||
|
|
||
|
|
||
| @tagged("post_install", "-at_install") | ||
| class TestSppIndicatorStudio(TransactionCase): | ||
| def test_module_is_installed(self): | ||
| module = self.env["ir.module.module"].search([("name", "=", "spp_indicator_studio")], limit=1) | ||
| self.assertTrue(module, "spp_indicator_studio not registered") | ||
| self.assertEqual( | ||
| module.state, | ||
| "installed", | ||
| f"spp_indicator_studio expected 'installed', got {module.state}", | ||
| ) | ||
|
|
||
| def test_indicator_views_loaded(self): | ||
| """views/indicator_views.xml declares list/form/kanban/action records.""" | ||
| for xml_id in ( | ||
| "spp_indicator_studio.spp_statistic_view_list", | ||
| "spp_indicator_studio.spp_statistic_view_form", | ||
| "spp_indicator_studio.spp_statistic_view_kanban", | ||
| "spp_indicator_studio.spp_statistic_action", | ||
| ): | ||
| with self.subTest(record=xml_id): | ||
| self.assertTrue( | ||
| self.env.ref(xml_id, raise_if_not_found=False), | ||
| f"{xml_id} missing — indicator_views.xml didn't load", | ||
| ) | ||
|
|
||
| def test_indicator_category_views_loaded(self): | ||
| """views/indicator_category_views.xml declares list/form/action records.""" | ||
| for xml_id in ( | ||
| "spp_indicator_studio.spp_metric_category_view_list", | ||
| "spp_indicator_studio.spp_metric_category_view_form", | ||
| "spp_indicator_studio.spp_metric_category_action", | ||
| ): | ||
| with self.subTest(record=xml_id): | ||
| self.assertTrue( | ||
| self.env.ref(xml_id, raise_if_not_found=False), | ||
| f"{xml_id} missing — indicator_category_views.xml didn't load", | ||
| ) | ||
|
|
||
| def test_indicator_action_targets_spp_indicator(self): | ||
| """The act_window must point at the spp.indicator model.""" | ||
| action = self.env.ref("spp_indicator_studio.spp_statistic_action", raise_if_not_found=False) | ||
| self.assertTrue(action) | ||
| self.assertEqual(action.res_model, "spp.indicator") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| from . import test_spp_starter_farmer_registry |
60 changes: 60 additions & 0 deletions
60
spp_starter_farmer_registry/tests/test_spp_starter_farmer_registry.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # Part of OpenSPP. See LICENSE file for full copyright and licensing details. | ||
| """Install / bundle-sanity tests for spp_starter_farmer_registry. | ||
|
|
||
| This is a meta-module / bundle — it only declares ``depends`` plus a | ||
| single ``ir.config_parameter`` seed. The tests verify that: | ||
|
|
||
| - the bundle itself installs cleanly, | ||
| - every farmer-registry dependency it bundles is reachable + installed, | ||
| - the seed config parameter loaded. | ||
| """ | ||
|
|
||
| from odoo.tests import TransactionCase, tagged | ||
|
|
||
|
|
||
| @tagged("post_install", "-at_install") | ||
| class TestSppStarterFarmerRegistry(TransactionCase): | ||
| """Spot-check that the bundle declared in __manifest__.py installs cleanly.""" | ||
|
|
||
| BUNDLE_DEPS = ( | ||
| "spp_starter_social_registry", | ||
| "spp_farmer_registry", | ||
| "spp_farmer_registry_vocabularies", | ||
| "spp_land_record", | ||
| "spp_irrigation", | ||
| "spp_gis", | ||
| "spp_programs", | ||
| ) | ||
|
|
||
| def test_module_is_installed(self): | ||
| module = self.env["ir.module.module"].search([("name", "=", "spp_starter_farmer_registry")], limit=1) | ||
| self.assertTrue(module, "spp_starter_farmer_registry not registered") | ||
| self.assertEqual( | ||
| module.state, | ||
| "installed", | ||
| f"spp_starter_farmer_registry expected 'installed', got {module.state}", | ||
| ) | ||
|
|
||
| def test_bundle_dependencies_installed(self): | ||
| """Every module in ``depends`` is itself installed.""" | ||
| Module = self.env["ir.module.module"] | ||
| for name in self.BUNDLE_DEPS: | ||
| with self.subTest(dep=name): | ||
| module = Module.search([("name", "=", name)], limit=1) | ||
| self.assertTrue(module, f"Bundle dep {name!r} not registered") | ||
| self.assertEqual( | ||
| module.state, | ||
| "installed", | ||
| f"Bundle dep {name!r} expected 'installed', got {module.state}", | ||
| ) | ||
|
|
||
| def test_smallholder_threshold_param_loaded(self): | ||
| """data/config_parameters.xml declares the smallholder threshold.""" | ||
| param = self.env.ref( | ||
| "spp_starter_farmer_registry.config_smallholder_threshold", | ||
| raise_if_not_found=False, | ||
| ) | ||
| self.assertTrue( | ||
| param, | ||
| "config_smallholder_threshold missing — config_parameters.xml didn't load", | ||
| ) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Searching for an arbitrary existing menu in the database can lead to flaky tests or unexpected failures if the selected menu already has restricted groups or other custom configurations. Creating a dedicated dummy menu for the test class ensures complete isolation and deterministic test behavior.