Skip to content

Test: start a test suite for migration utils functions#8225

Open
CarolineDenis wants to merge 93 commits into
v7_12_0_7_basefrom
issue-8224
Open

Test: start a test suite for migration utils functions#8225
CarolineDenis wants to merge 93 commits into
v7_12_0_7_basefrom
issue-8224

Conversation

@CarolineDenis

@CarolineDenis CarolineDenis commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Fixes #8224
Fixes #8049
Fixes #8042

Checklist

  • Self-review the PR after opening it to make sure the changes look good and
    self-explanatory (or properly documented)
  • Add relevant issue to release milestone
  • Add pr to documentation list
  • Add automated tests
  • Add a reverse migration if a migration is present in the PR
  • Add migration function to
    def fix_schema_config(stdout: WriteToStdOut | None = None):

Testing instructions

Summary by CodeRabbit

  • Bug Fixes

    • Improved migration reliability and idempotency across several data/schema update paths.
    • Fixed duplicate-record handling and ensured repeated migration runs no longer create extra entries.
    • Corrected handling of default values, hidden fields, and related schema updates for several core data types.
  • Tests

    • Added broad coverage for migration commands and helper workflows.
    • Expanded database-backed tests for schema updates, deduplication, and rollback behavior.

@CarolineDenis CarolineDenis added this to the 7.12.0.7 milestone Jun 16, 2026
@github-project-automation github-project-automation Bot moved this to 📋Back Log in General Tester Board Jun 16, 2026
@CarolineDenis CarolineDenis linked an issue Jun 16, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4eddd41d-87db-402f-a7be-c4ffb0f60cfb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds extensive Django/unittest coverage for specifyweb/specify/migration_utils helper functions (bulk creation, schema reader/writer, deduplication, default COT/tectonic setup, and numerous versioned migration helpers) and for the run_key_migration_functions management command (dispatch order, section behaviors, and record-count idempotency). It also updates a few import paths and makes an exception re-raise in the command.

Changes

Migration Utils Unit Test Suite

Layer / File(s) Summary
Tests package init and bulk-create idempotency
specifyweb/specify/migration_utils/tests/__init__.py, .../test_bulk_create.py
Initializes the tests package and adds tests validating idempotent bulk_create_splocaleitemstr_idempotent behavior.
Helper 0003 cotype picklist test
.../test_helper_0003_cotype_picklist.py
Verifies picklist and schema container item/string creation per collection.
Schema reader tests
.../test_schema_reader.py
Covers hidden-override detection, JSON normalization, and string/type helpers.
Schema writer tests
.../test_schema_writer.py
Covers default schema config creation and revert deletion logic.
Deduplication tests
.../test_deduplication.py
Covers SQL and ORM-based deduplication of schema config containers/items/strings.
Default COTs and treedef tests
.../test_default_cots.py
Covers collection type creation, discipline/institution linking, and picklist creation.
Tectonic ranks tests
.../test_tectonic_ranks.py
Covers default rank/root creation and treedef discipline link fixes.
Helper 0031 & 0039 tests
.../test_helper_0031_add_default_for_selectseries.py, .../test_helper_0039_agent_fields_for_loan_and_gift.py
Verifies selectseries default normalization and loan/gift field hiding.
Additional versioned helper tests (0004–0042)
.../test_helper_0004_...py ... .../test_helper_0042_...py, migration_helpers/__init__.py, helper_0017_schemaconfig_fixes.py
Covers numerous individual migration helpers plus MIGRATION_0008_FIELDS import source updates.

Management Command Test Infrastructure and Integration Tests

Layer / File(s) Summary
Command import and exception updates
run_key_migration_functions.py, migrations/0008_ageCitations_fix.py, migrations/0031_add_default_for_selectseries.py
Switches import sources for update_relative_age_fields/make_selectseries_false and re-raises exceptions in Command.handle.
Test base infrastructure
tests/test_migration_base.py
Adds MigrationCommandTestCase/MigrationDatabaseTestCase with recorder-based section call assertions.
Command dispatch tests
tests/command_tests.py
Verifies dispatch order, verbose/stdout handling, apply_patches, and unknown function errors.
Section order tests
tests/test_run_key_migration_functions_order.py
Verifies section execution order and internal function ordering for tectonic/misc sections.
App resource, business rules, cots, permissions, schema config, tectonic section tests
tests/app_resource_tests.py, tests/business_rules_tests.py, tests/cots_tests.py, tests/permissions_tests.py, tests/schema_config_tests.py, tests/tectonic_tests.py
Adds database-backed and mocked tests for each migration section's behavior.
Discipline resource dir dedup test
tests/test_deduplicate_discipline.py
Verifies deduplication preserves non-empty/scoped resource directories.
Idempotency integration test
tests/test_run_key_migration_functions.py
Verifies the command produces no duplicate records across repeated runs with simulated Specify 7 usage data.

Possibly related PRs

  • specify/specify7#6308: Introduced the run_key_migration_functions command that this PR now covers with tests and import/exception changes.
  • specify/specify7#8039: Fixed duplicate splocalecontainer creation; this PR adds direct test coverage for the same idempotency behavior.
  • specify/specify7#8223: Refactored migration_utils (schema_reader, schema_writer, deduplication); this PR adds the corresponding test coverage.

Suggested reviewers: grantfitzsimmons

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Testing Instructions ⚠️ Warning The PR leaves the Testing instructions section blank, so it doesn’t explain how to verify the changed command and migration helpers or the new tests. Add concrete steps, e.g. run the affected test modules and note any migration-specific checks for run_key_migration_functions and the helper updates.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the PR’s main focus on adding migration-utils test coverage.
Linked Issues check ✅ Passed The PR adds unit tests for run_key_migration_functions dispatch/order/idempotency and key migration helpers, matching #8049 and #8042.
Out of Scope Changes check ✅ Passed No clear unrelated feature work stands out; the non-test code changes appear tied to the new migration coverage.
Automatic Tests ✅ Passed PR adds extensive automated test coverage: many new test modules plus shared test bases for the migration command and migration utils.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-8224

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@CarolineDenis

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (1)
specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py (1)

63-63: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Same issue: passing _mock_new_parent instead of a proper apps mock.

This line has the same problem as line 36. Use a proper mock apps object.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py`
at line 63, The call to create_cotype_splocalecontaineritem is passing
mock_container._mock_new_parent as the apps argument, but this should be a
proper mock apps object instead. Replace the _mock_new_parent argument with a
properly constructed mock apps object (following the same pattern used to fix
the similar issue at line 36) to ensure the test passes the correct type of
dependency to the function.
🧹 Nitpick comments (1)
specifyweb/specify/migration_utils/tests/test_schema_reader.py (1)

122-122: 💤 Low value

Remove trailing blank line.

The file ends with an extra blank line after the closing of the if __name__ == '__main__' block.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_schema_reader.py` at line 122,
There is an extra blank line at the end of the file after the if __name__ ==
'__main__' block. Remove the trailing blank line at the end of the
test_schema_reader.py file to clean up the file formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specifyweb/specify/migration_utils/tests/test_bulk_create.py`:
- Around line 46-50: The test is named with "idempotent" but doesn't actually
verify idempotent behavior. After the first assertion where result equals 2, add
a second call to the same function being tested using the same input rows, then
assert that this second call returns 0 to confirm that no duplicate rows are
created. This verifies that the function properly checks for existing rows and
avoids redundant bulk_create operations when called with identical data.
- Around line 16-22: The mock queryset setup in the test does not properly
simulate the chained filter calls used in the real function. The real
implementation calls filter twice in succession before order_by, but the current
mock setup only chains filter once. Modify the mock_qs setup so that the first
filter call returns an object whose filter method can be called again, and that
second filter call returns an object with an order_by method. Specifically,
ensure mock_qs.filter.return_value has its own filter method configured to
return an object that has order_by chained properly, allowing the double filter
pattern to work correctly.
- Around line 11-12: The `@patch` decorator is replacing the actual
bulk_create_splocaleitemstr_idempotent function with a mock, preventing the test
from verifying the real implementation logic. Remove the `@patch` decorator
entirely and instead mock only the internal ORM dependencies (like
model.objects.filter and model.objects.bulk_create) that the actual function
uses. Update the test assertions to verify that the real function correctly
calls these mocked ORM methods with the expected parameters (FK filters,
language filters, and bulk_create calls), rather than asserting on the mock of
the function itself.

In
`@specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py`:
- Line 36: The function create_cotype_splocalecontaineritem is being called with
mock_container._mock_new_parent, which is an internal MagicMock attribute and
not a valid apps object with the required get_model method. Create a proper mock
apps object that implements the get_model(app_label, model_name) method as
expected by the function signature, then pass this mock apps object as the
argument to the create_cotype_splocalecontaineritem call instead of the
_mock_new_parent attribute.
- Around line 9-11: The test is patching module-level names that don't actually
exist in helper_0003_cotype_picklist.py, but the real
create_cotype_splocalecontaineritem function dynamically obtains models using
apps.get_model('specify', ModelName). Replace the three `@patch` decorators
targeting Splocalecontainer, Splocalecontaineritem, and Splocaleitemstr with a
single `@patch` for the apps parameter, then configure apps.get_model.side_effect
to return the appropriate mock models based on the model name argument passed to
it. Apply this same pattern to both test methods in the file.

In `@specifyweb/specify/migration_utils/tests/test_schema_reader.py`:
- Around line 28-48: The test assertion for mock_path is incorrect because it
expects the full concatenated path string, but the actual function constructs
the path using chained division operators starting with
Path(settings.SPECIFY_CONFIG_DIR). Update the test to properly mock the Path
chaining behavior by setting up mock_path.return_value to support the
__truediv__ method (which implements the / operator) and chain operations, then
correct the assertion to expect mock_path to be called once with just "/config"
instead of the full path string. The mock path instance should also have
exists() and open() methods properly configured to support the chaining pattern.

In `@specifyweb/specify/migration_utils/tests/test_schema_writer.py`:
- Around line 12-16: The test patches are targeting non-existent module-level
imports in schema_writer, but the real
`update_table_schema_config_with_defaults` function obtains models through
`apps.get_model()` calls, not from direct imports. Instead of patching
`Splocalecontainer`, `Splocalecontaineritem`, `Splocaleitemstr` as if they were
module-level imports, create a mock `apps` object, configure its `get_model()`
method to return the appropriate mock models for each model name (specify,
Splocalecontainer), (specify, Splocalecontaineritem), and (specify,
Splocaleitemstr), and pass this mock as a parameter to the
`update_table_schema_config_with_defaults` function call in the test. Also patch
the `apps` import in the schema_writer module itself.
- Around line 65-72: The test is patching module-level names that the function
`revert_table_schema_config` does not use. Instead, the function obtains models
via `apps.get_model()`, but the test calls
`revert_table_schema_config("TestTable")` without passing an `apps` argument,
causing it to use the real Django registry (global_apps). Remove the three
`@patch` decorators for Splocalecontainer, Splocaleitemstr, and
Splocalecontaineritem. Instead, create a mock `apps` object that is configured
to return the mocked model instances when `get_model()` is called with the
appropriate model names, and pass this mock `apps` object as a parameter to the
`revert_table_schema_config` function call.

---

Duplicate comments:
In
`@specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py`:
- Line 63: The call to create_cotype_splocalecontaineritem is passing
mock_container._mock_new_parent as the apps argument, but this should be a
proper mock apps object instead. Replace the _mock_new_parent argument with a
properly constructed mock apps object (following the same pattern used to fix
the similar issue at line 36) to ensure the test passes the correct type of
dependency to the function.

---

Nitpick comments:
In `@specifyweb/specify/migration_utils/tests/test_schema_reader.py`:
- Line 122: There is an extra blank line at the end of the file after the if
__name__ == '__main__' block. Remove the trailing blank line at the end of the
test_schema_reader.py file to clean up the file formatting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 09e00975-8c37-4bc2-91a7-45fae919b02c

📥 Commits

Reviewing files that changed from the base of the PR and between 4c752cc and 6c779a5.

📒 Files selected for processing (5)
  • specifyweb/specify/migration_utils/tests/__init__.py
  • specifyweb/specify/migration_utils/tests/test_bulk_create.py
  • specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py
  • specifyweb/specify/migration_utils/tests/test_schema_reader.py
  • specifyweb/specify/migration_utils/tests/test_schema_writer.py

Comment thread specifyweb/specify/migration_utils/tests/test_bulk_create.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_bulk_create.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_bulk_create.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_schema_reader.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_schema_writer.py Outdated
Comment thread specifyweb/specify/migration_utils/tests/test_schema_writer.py Outdated
@github-project-automation github-project-automation Bot moved this from 📋Back Log to Dev Attention Needed in General Tester Board Jun 17, 2026
@CarolineDenis

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Base automatically changed from issue-8124-8126-fix-7660-7682-2-after-review-2 to v7_12_0_7_base June 30, 2026 12:42
@CarolineDenis

Copy link
Copy Markdown
Contributor Author

@CodeRabbit full review

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (7)
specifyweb/specify/management/commands/tests/business_rules_tests.py (1)

66-105: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Test does not cover the multi-field exclusion branch of catnum_rule_editable.

The upstream helper (specifyweb/backend/businessrules/migration_utils.py) explicitly guards against rules with more than one scope/field via len(fields) == 1 and len(scopes) == 1, since .get() raises if more than one match. This test only covers exact-match and different-field-path cases, leaving the multi-field guard unverified.

♻️ Suggested additional case
+        multi_field_rule = UniquenessRule.objects.create(
+            modelName="Collectionobject",
+            discipline=discipline,
+            isDatabaseConstraint=True,
+        )
+        UniquenessRuleField.objects.create(
+            uniquenessrule=multi_field_rule,
+            fieldPath="catalogNumber",
+            isScope=False,
+        )
+        UniquenessRuleField.objects.create(
+            uniquenessrule=multi_field_rule,
+            fieldPath="collection",
+            isScope=True,
+        )
+        UniquenessRuleField.objects.create(
+            uniquenessrule=multi_field_rule,
+            fieldPath="collectionobjecttype",
+            isScope=True,
+        )
+
         rkm.catnum_rule_editable(django_apps)

         matching_rule.refresh_from_db()
         nonmatching_rule.refresh_from_db()
+        multi_field_rule.refresh_from_db()
         self.assertFalse(matching_rule.isDatabaseConstraint)
         self.assertTrue(nonmatching_rule.isDatabaseConstraint)
+        self.assertTrue(multi_field_rule.isDatabaseConstraint)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/management/commands/tests/business_rules_tests.py` around
lines 66 - 105, The
`BusinessRulesDatabaseTests.test_catnum_rule_editable_only_updates_matching_catalog_number_rule`
test is missing coverage for the multi-field exclusion branch in
`catnum_rule_editable`. Add a case that creates a `UniquenessRule` with more
than one non-scope field or more than one scope field, then call
`rkm.catnum_rule_editable(django_apps)` and assert that this rule remains
unchanged. Use the existing `UniquenessRule` and `UniquenessRuleField` setup
patterns so the test verifies the `len(fields) == 1 and len(scopes) == 1` guard
in `migration_utils`.
specifyweb/specify/migration_utils/tests/test_schema_reader.py (1)

120-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Finish or drop the commented-out find_missing_schema_config_fields test.

This test is fully disabled behind a #TODO, leaving find_missing_schema_config_fields (imported at line 14 but otherwise untested) without coverage — one of the utilities this PR's objectives call out for testing.

Want me to flesh out this test (fixing the mock_table._all_fields return value to use real field-name attributes matching the actual signature) or should this be tracked as a follow-up issue?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_schema_reader.py` around lines
120 - 159, Either restore the disabled find_missing_schema_config_fields test or
remove the dead scaffold entirely; the current `#TODO` leaves this utility
untested despite being imported and intended for coverage. If you keep it,
update test_find_missing_schema_config_fields to match the real
schema_reader/find_missing_schema_config_fields behavior, including mocking
datamodel and global_apps correctly and using _all_fields values that expose the
actual field-name attribute expected by the implementation.
specifyweb/specify/migration_utils/tests/test_helper_0039_agent_fields_for_loan_and_gift.py (1)

14-21: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded call count is fragile vs. sibling tests.

10 implicitly assumes exactly one Discipline fixture row. Sibling tests in this cohort (e.g. test_helper_0004_stratigraphy_age.py, test_helper_0008_ageCitations_fix.py, test_helper_0012_add_cojo_to_schema_config.py) compute the expected count dynamically from Discipline.objects.count() × field count, which is more resilient to fixture changes.

♻️ Proposed fix for consistency
+from specifyweb.specify.models import Discipline
+
     def test_calls_schema_writer_for_all_fields(self, mock_update):

         helper.update_loan_and_gift_agent_fields(django_apps)

-        self.assertEqual(mock_update.call_count, 10)
+        expected = Discipline.objects.count() * sum(
+            len(fields) for fields in helper.MIGRATION_0039_FIELDS.values()
+        )
+        self.assertEqual(mock_update.call_count, expected)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@specifyweb/specify/migration_utils/tests/test_helper_0039_agent_fields_for_loan_and_gift.py`
around lines 14 - 21, The test in test_calls_schema_writer_for_all_fields is
hardcoding the expected update count, which makes it brittle if fixture data
changes. Update the assertion to derive the expected number of calls from the
current Discipline.objects.count() multiplied by the number of fields updated by
helper.update_loan_and_gift_agent_fields, matching the pattern used in the
sibling migration helper tests. Keep the kwargs["defaults"] check as-is to
verify each schema update remains hidden.
specifyweb/specify/migration_utils/tests/test_helper_0040_components.py (1)

93-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate container+name="type" items in setUp.

self.component_type_item (Line 26-31) and self.hidden_field (Line 100-105) both use container=self.component_container, name="type". Filters like create_cotype_splocalecontaineritem_for_components match on container+name and will affect both rows via .update(), which happens to not break current assertions, but it's fragile if a future helper expects a single unique row per container/name.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_helper_0040_components.py`
around lines 93 - 105, `TestHelper0040Components.setUp` creates two
Splocalecontaineritem rows with the same `container=self.component_container`
and `name="type"`, which makes later helpers like
`create_cotype_splocalecontaineritem_for_components` ambiguous because they
update by container+name. Change the test fixture so only one `type` item exists
per component container, or use a different name for `hidden_field`, and keep
the existing references (`self.component_type_item`, `self.hidden_field`)
aligned with the intended uniqueness.
specifyweb/specify/migration_utils/tests/test_tectonic_ranks.py (1)

209-271: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strengthen assertions on constructed Tectonicunittreedef objects.

test_creates_missing_tree_defs_and_updates_discipline_links only checks len(bulk_create_args) == 3 and re-asserts bulk_create was called with the same list object it just captured (a tautology that can't catch a regression). It doesn't verify that each constructed model instance actually received the correct discipline_id (1, 2, 3) and name="Tectonic Unit". Since TectonicTreeDef_Model is a MagicMock, its call_args_list can be inspected directly to catch wrong-field regressions in _create_tectonic_unit_for_discipline.

♻️ Suggested strengthening
         TectonicTreeDef_Model.objects.bulk_create.assert_called_once_with(
             bulk_create_args,
             batch_size=1000,
         )
+
+        TectonicTreeDef_Model.assert_has_calls(
+            [
+                call(name="Tectonic Unit", discipline_id=disciplineid)
+                for disciplineid in missing_disciplines
+            ]
+        )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_tectonic_ranks.py` around lines
209 - 271, The test only checks list length and reuses the same bulk_create
argument, so it misses regressions in how `_create_tectonic_unit_for_discipline`
builds `Tectonicunittreedef` instances. Update
`test_creates_missing_tree_defs_and_updates_discipline_links` to inspect
`TectonicTreeDef_Model.call_args_list` (or the created objects passed to
`bulk_create`) and assert each instance was constructed with the expected
`discipline_id` values 1, 2, and 3 and `name="Tectonic Unit"`. Keep the existing
`bulk_create` and update assertions, but make the object-field checks the core
validation.
specifyweb/specify/management/commands/tests/tectonic_tests.py (1)

36-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Static analysis: add strict= to zip().

Ruff flags this zip() call without an explicit strict= parameter (B905). Here items and items[1:] always differ by exactly one element by construction, so there's no real truncation risk, but adding strict=False (or using itertools.pairwise(items)) satisfies the linter and documents intent.

🧹 Suggested fix
-        for parent, child in zip(items, items[1:]):
+        for parent, child in zip(items, items[1:], strict=False):
             self.assertEqual(child.parent_id, parent.id)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/management/commands/tests/tectonic_tests.py` around lines
36 - 37, Add an explicit strict argument to the zip in the test loop that
iterates over items and items[1:] so Ruff B905 is satisfied. Update the
parent/child iteration in the tectonic test to use zip(..., strict=False), or
switch to itertools.pairwise in that test helper if you prefer clearer intent,
keeping the assertion on child.parent_id unchanged.

Source: Linters/SAST tools

specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py (1)

26-46: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

TRACKED_MODELS omits models created by simulate_specify7_usage.

Collectionobject, Spappresource, and Spappresourcedata are created in simulate_specify7_usage (lines 111-177) but aren't tracked in TRACKED_MODELS. If a migration section were to accidentally duplicate or drop any of these on a rerun, count_diff wouldn't detect it — weakening the idempotency guarantee this test is meant to prove.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py`
around lines 26 - 46, TRACKED_MODELS is missing several models that
`simulate_specify7_usage` creates, so the idempotency check in `count_diff` can
miss duplicate or dropped rows. Add the missing tracked entries for
`Collectionobject`, `Spappresource`, and `Spappresourcedata` to `TRACKED_MODELS`
so the test covers all models touched by `simulate_specify7_usage`.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@specifyweb/specify/management/commands/tests/business_rules_tests.py`:
- Line 68: Populate the required fields when creating the test Discipline in
business_rules_tests instead of using only name. Update the
Discipline.objects.create call in the test setup to supply division, datatype,
geographytreedef, and geologictimeperiodtreedef so the fixture can be created
successfully before reaching catnum_rule_editable.

In `@specifyweb/specify/management/commands/tests/schema_config_tests.py`:
- Around line 31-77: The test’s ordered helper list in schema_config_tests is
missing update_loan_and_gift_agent_fields, so it is not being patched and the
real helper can run against FakeApps. Add update_loan_and_gift_agent_fields to
the names sequence in the same position used by fix_schema_config, and keep the
expected calls assertion in sync so the recorder order matches the actual
workflow.

In
`@specifyweb/specify/management/commands/tests/test_run_key_migration_functions_order.py`:
- Around line 20-48: This test class duplicates helper logic that already exists
in MigrationCommandTestCase, so refactor KeyMigrationSectionTests to inherit
from that base instead of redefining _recorder, _patch_recorders, and
_assert_section_calls. Keep the test body focused on key migration ordering and
rely on the shared helpers from MigrationCommandTestCase, matching the approach
used by command_tests.py. Remove the copied helper methods and update the class
hierarchy so the shared behavior is reused from the existing base test class.

In
`@specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py`:
- Around line 374-386: The first-run backfill behavior is not being verified
because first_run_diff is computed in the run_key_migration_functions test but
never asserted. Update this test to make a meaningful assertion about the
initial change in record_counts/count_diff after the first call to
run_key_migration_functions, using first_run_diff to confirm the expected
migration records were created or backfilled on the first run.

In `@specifyweb/specify/migration_utils/tests/test_helper_0040_components.py`:
- Around line 195-202: The test_reverse_hide_component_fields assertion is
inverted: after calling reverse_hide_component_fields(apps), the hidden_field
should be verified as unhidden. Update the final assertion in
test_reverse_hide_component_fields so it checks the refreshed
self.hidden_field.ishidden is False, matching the behavior of
helper_0040_components.reverse_hide_component_fields.

In
`@specifyweb/specify/migration_utils/tests/test_helper_0042_discipline_type_picklist.py`:
- Around line 135-147: The revert test in
DisciplineTypeSplocaleContainerItemRevertTests does not exercise the migration
logic because it never creates the matching
Splocalecontainer/Splocalecontaineritem fixture and only asserts
Collection.objects.all().exists(), which is unrelated. Update
test_revert_splocalecontaineritem to mirror the sibling update test by creating
the exact filtered fixture before calling
helper_0042_discipline_type_picklist.update_discipline_type_splocalecontaineritem
and
helper_0042_discipline_type_picklist.revert_discipline_type_splocalecontaineritem,
then assert on the reverted Splocalecontaineritem field state rather than
collection existence.

---

Nitpick comments:
In `@specifyweb/specify/management/commands/tests/business_rules_tests.py`:
- Around line 66-105: The
`BusinessRulesDatabaseTests.test_catnum_rule_editable_only_updates_matching_catalog_number_rule`
test is missing coverage for the multi-field exclusion branch in
`catnum_rule_editable`. Add a case that creates a `UniquenessRule` with more
than one non-scope field or more than one scope field, then call
`rkm.catnum_rule_editable(django_apps)` and assert that this rule remains
unchanged. Use the existing `UniquenessRule` and `UniquenessRuleField` setup
patterns so the test verifies the `len(fields) == 1 and len(scopes) == 1` guard
in `migration_utils`.

In `@specifyweb/specify/management/commands/tests/tectonic_tests.py`:
- Around line 36-37: Add an explicit strict argument to the zip in the test loop
that iterates over items and items[1:] so Ruff B905 is satisfied. Update the
parent/child iteration in the tectonic test to use zip(..., strict=False), or
switch to itertools.pairwise in that test helper if you prefer clearer intent,
keeping the assertion on child.parent_id unchanged.

In
`@specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py`:
- Around line 26-46: TRACKED_MODELS is missing several models that
`simulate_specify7_usage` creates, so the idempotency check in `count_diff` can
miss duplicate or dropped rows. Add the missing tracked entries for
`Collectionobject`, `Spappresource`, and `Spappresourcedata` to `TRACKED_MODELS`
so the test covers all models touched by `simulate_specify7_usage`.

In
`@specifyweb/specify/migration_utils/tests/test_helper_0039_agent_fields_for_loan_and_gift.py`:
- Around line 14-21: The test in test_calls_schema_writer_for_all_fields is
hardcoding the expected update count, which makes it brittle if fixture data
changes. Update the assertion to derive the expected number of calls from the
current Discipline.objects.count() multiplied by the number of fields updated by
helper.update_loan_and_gift_agent_fields, matching the pattern used in the
sibling migration helper tests. Keep the kwargs["defaults"] check as-is to
verify each schema update remains hidden.

In `@specifyweb/specify/migration_utils/tests/test_helper_0040_components.py`:
- Around line 93-105: `TestHelper0040Components.setUp` creates two
Splocalecontaineritem rows with the same `container=self.component_container`
and `name="type"`, which makes later helpers like
`create_cotype_splocalecontaineritem_for_components` ambiguous because they
update by container+name. Change the test fixture so only one `type` item exists
per component container, or use a different name for `hidden_field`, and keep
the existing references (`self.component_type_item`, `self.hidden_field`)
aligned with the intended uniqueness.

In `@specifyweb/specify/migration_utils/tests/test_schema_reader.py`:
- Around line 120-159: Either restore the disabled
find_missing_schema_config_fields test or remove the dead scaffold entirely; the
current `#TODO` leaves this utility untested despite being imported and intended
for coverage. If you keep it, update test_find_missing_schema_config_fields to
match the real schema_reader/find_missing_schema_config_fields behavior,
including mocking datamodel and global_apps correctly and using _all_fields
values that expose the actual field-name attribute expected by the
implementation.

In `@specifyweb/specify/migration_utils/tests/test_tectonic_ranks.py`:
- Around line 209-271: The test only checks list length and reuses the same
bulk_create argument, so it misses regressions in how
`_create_tectonic_unit_for_discipline` builds `Tectonicunittreedef` instances.
Update `test_creates_missing_tree_defs_and_updates_discipline_links` to inspect
`TectonicTreeDef_Model.call_args_list` (or the created objects passed to
`bulk_create`) and assert each instance was constructed with the expected
`discipline_id` values 1, 2, and 3 and `name="Tectonic Unit"`. Keep the existing
`bulk_create` and update assertions, but make the object-field checks the core
validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bf7768a4-f685-4e69-90ab-fc19ea9fe131

📥 Commits

Reviewing files that changed from the base of the PR and between fdfdaa3 and 6fa769f.

📒 Files selected for processing (49)
  • specifyweb/specify/management/commands/run_key_migration_functions.py
  • specifyweb/specify/management/commands/tests/__init__.py
  • specifyweb/specify/management/commands/tests/app_resource_tests.py
  • specifyweb/specify/management/commands/tests/business_rules_tests.py
  • specifyweb/specify/management/commands/tests/command_tests.py
  • specifyweb/specify/management/commands/tests/cots_tests.py
  • specifyweb/specify/management/commands/tests/permissions_tests.py
  • specifyweb/specify/management/commands/tests/schema_config_tests.py
  • specifyweb/specify/management/commands/tests/tectonic_tests.py
  • specifyweb/specify/management/commands/tests/test_deduplicate_discipline.py
  • specifyweb/specify/management/commands/tests/test_migration_base.py
  • specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py
  • specifyweb/specify/management/commands/tests/test_run_key_migration_functions_order.py
  • specifyweb/specify/migration_utils/migration_helpers/__init__.py
  • specifyweb/specify/migration_utils/migration_helpers/helper_0003_cotype_picklist.py
  • specifyweb/specify/migration_utils/migration_helpers/helper_0008_ageCitations_fix.py
  • specifyweb/specify/migration_utils/migration_helpers/helper_0017_schemaconfig_fixes.py
  • specifyweb/specify/migration_utils/migration_helpers/helper_0031_add_default_for_selectseries.py
  • specifyweb/specify/migration_utils/tests/__init__.py
  • specifyweb/specify/migration_utils/tests/test_bulk_create.py
  • specifyweb/specify/migration_utils/tests/test_deduplication.py
  • specifyweb/specify/migration_utils/tests/test_default_cots.py
  • specifyweb/specify/migration_utils/tests/test_helper_0003_cotype_picklist.py
  • specifyweb/specify/migration_utils/tests/test_helper_0004_stratigraphy_age.py
  • specifyweb/specify/migration_utils/tests/test_helper_0007_schema_config_update.py
  • specifyweb/specify/migration_utils/tests/test_helper_0008_ageCitations_fix.py
  • specifyweb/specify/migration_utils/tests/test_helper_0012_add_cojo_to_schema_config.py
  • specifyweb/specify/migration_utils/tests/test_helper_0013_collectionobjectgroup_parentcog.py
  • specifyweb/specify/migration_utils/tests/test_helper_0015_add_version_to_ages.py
  • specifyweb/specify/migration_utils/tests/test_helper_0017_schemaconfig_fixes.py
  • specifyweb/specify/migration_utils/tests/test_helper_0018_cot_catnum_schema.py
  • specifyweb/specify/migration_utils/tests/test_helper_0020_add_tectonicunit_to_pc_in_schema_config.py
  • specifyweb/specify/migration_utils/tests/test_helper_0021_update_hidden_geo_tables.py
  • specifyweb/specify/migration_utils/tests/test_helper_0023_update_schema_config_text.py
  • specifyweb/specify/migration_utils/tests/test_helper_0024_add_uniqueIdentifier_storage.py
  • specifyweb/specify/migration_utils/tests/test_helper_0027_CO_children.py
  • specifyweb/specify/migration_utils/tests/test_helper_0031_add_default_for_selectseries.py
  • specifyweb/specify/migration_utils/tests/test_helper_0032_add_quantities_gift.py
  • specifyweb/specify/migration_utils/tests/test_helper_0033_update_paleo_desc.py
  • specifyweb/specify/migration_utils/tests/test_helper_0034_accession_date_fields.py
  • specifyweb/specify/migration_utils/tests/test_helper_0035_version_required.py
  • specifyweb/specify/migration_utils/tests/test_helper_0039_agent_fields_for_loan_and_gift.py
  • specifyweb/specify/migration_utils/tests/test_helper_0040_components.py
  • specifyweb/specify/migration_utils/tests/test_helper_0042_discipline_type_picklist.py
  • specifyweb/specify/migration_utils/tests/test_schema_reader.py
  • specifyweb/specify/migration_utils/tests/test_schema_writer.py
  • specifyweb/specify/migration_utils/tests/test_tectonic_ranks.py
  • specifyweb/specify/migrations/0008_ageCitations_fix.py
  • specifyweb/specify/migrations/0031_add_default_for_selectseries.py
💤 Files with no reviewable changes (1)
  • specifyweb/specify/migration_utils/migration_helpers/helper_0003_cotype_picklist.py

Comment thread specifyweb/specify/management/commands/tests/business_rules_tests.py Outdated
Comment on lines +31 to +77
names = [
# Ordered per fix_schema_config implementation
"create_geo_table_schema_config_with_defaults",
"create_cotype_splocalecontaineritem",
"create_strat_table_schema_config_with_defaults",
"create_agetype_picklist",
"create_cogtype_picklist",
"update_relative_age_fields",
"add_cojo_to_schema_config",
"update_cog_schema_config",
"update_age_schema_config",
"add_tectonicunit_to_pc_in_schema_config",
"update_storage_unique_id_fields",
"remove_componentparent_item",
"create_table_schema_config_with_defaults",
"create_discipline_type_picklist",
"apply_schema_overrides_for_all_disciplines",
"deduplicate_schema_config_orm",
]
fake_apps = FakeApps()

with ExitStack() as stack:
stack.enter_context(patch.object(rkm, "apps", fake_apps))
self._patch_recorders(stack, [(rkm.usc, name) for name in names], calls)
schema_defaults_apply_path = (
"specifyweb.backend.setup_tool.schema_defaults."
"apply_schema_defaults_task.apply"
)
stack.enter_context(
patch(
schema_defaults_apply_path,
apply_schema_defaults,
)
)

rkm.fix_schema_config(stdout)

self.assertEqual(fake_apps.model_request, ("specify", "Discipline"))
self.assertEqual(
calls,
[(name, fake_apps) for name in names[:-1]]
+ [
("apply_schema_defaults_task.apply", [discipline_1.id]),
("apply_schema_defaults_task.apply", [discipline_2.id]),
(names[-1], fake_apps),
],
)

@coderabbitai coderabbitai Bot Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Missing update_loan_and_gift_agent_fields from the names list breaks the test.

The real fix_schema_config funcs list includes update_loan_and_gift_agent_fields between update_storage_unique_id_fields and remove_componentparent_item, but it's absent from names here. Since only functions in names get patched via self._patch_recorders, the real unmocked helper runs against fake_apps (whose get_model returns a bare FakeDiscipline/SimpleNamespace lacking ORM methods) — likely raising an exception before the test can even reach its assertions, and breaking the exact-order calls assertion regardless.

🐛 Proposed fix
             "update_storage_unique_id_fields",
+            "update_loan_and_gift_agent_fields",
             "remove_componentparent_item",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
names = [
# Ordered per fix_schema_config implementation
"create_geo_table_schema_config_with_defaults",
"create_cotype_splocalecontaineritem",
"create_strat_table_schema_config_with_defaults",
"create_agetype_picklist",
"create_cogtype_picklist",
"update_relative_age_fields",
"add_cojo_to_schema_config",
"update_cog_schema_config",
"update_age_schema_config",
"add_tectonicunit_to_pc_in_schema_config",
"update_storage_unique_id_fields",
"remove_componentparent_item",
"create_table_schema_config_with_defaults",
"create_discipline_type_picklist",
"apply_schema_overrides_for_all_disciplines",
"deduplicate_schema_config_orm",
]
fake_apps = FakeApps()
with ExitStack() as stack:
stack.enter_context(patch.object(rkm, "apps", fake_apps))
self._patch_recorders(stack, [(rkm.usc, name) for name in names], calls)
schema_defaults_apply_path = (
"specifyweb.backend.setup_tool.schema_defaults."
"apply_schema_defaults_task.apply"
)
stack.enter_context(
patch(
schema_defaults_apply_path,
apply_schema_defaults,
)
)
rkm.fix_schema_config(stdout)
self.assertEqual(fake_apps.model_request, ("specify", "Discipline"))
self.assertEqual(
calls,
[(name, fake_apps) for name in names[:-1]]
+ [
("apply_schema_defaults_task.apply", [discipline_1.id]),
("apply_schema_defaults_task.apply", [discipline_2.id]),
(names[-1], fake_apps),
],
)
names = [
# Ordered per fix_schema_config implementation
"create_geo_table_schema_config_with_defaults",
"create_cotype_splocalecontaineritem",
"create_strat_table_schema_config_with_defaults",
"create_agetype_picklist",
"create_cogtype_picklist",
"update_relative_age_fields",
"add_cojo_to_schema_config",
"update_cog_schema_config",
"update_age_schema_config",
"add_tectonicunit_to_pc_in_schema_config",
"update_storage_unique_id_fields",
"update_loan_and_gift_agent_fields",
"remove_componentparent_item",
"create_table_schema_config_with_defaults",
"create_discipline_type_picklist",
"apply_schema_overrides_for_all_disciplines",
"deduplicate_schema_config_orm",
]
fake_apps = FakeApps()
with ExitStack() as stack:
stack.enter_context(patch.object(rkm, "apps", fake_apps))
self._patch_recorders(stack, [(rkm.usc, name) for name in names], calls)
schema_defaults_apply_path = (
"specifyweb.backend.setup_tool.schema_defaults."
"apply_schema_defaults_task.apply"
)
stack.enter_context(
patch(
schema_defaults_apply_path,
apply_schema_defaults,
)
)
rkm.fix_schema_config(stdout)
self.assertEqual(fake_apps.model_request, ("specify", "Discipline"))
self.assertEqual(
calls,
[(name, fake_apps) for name in names[:-1]]
[
("apply_schema_defaults_task.apply", [discipline_1.id]),
("apply_schema_defaults_task.apply", [discipline_2.id]),
(names[-1], fake_apps),
],
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/management/commands/tests/schema_config_tests.py` around
lines 31 - 77, The test’s ordered helper list in schema_config_tests is missing
update_loan_and_gift_agent_fields, so it is not being patched and the real
helper can run against FakeApps. Add update_loan_and_gift_agent_fields to the
names sequence in the same position used by fix_schema_config, and keep the
expected calls assertion in sync so the recorder order matches the actual
workflow.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, something went wrong! Please try again later. 🐰 💔

Comment on lines +374 to +386
before_first_run = record_counts()

self.run_key_migration_functions(
"fix_schema_config",
"fix_app_resource_dirs",
"fix_permissions",
"fix_business_rules",
"fix_tectonic_ranks",
"fix_misc",
)

after_first_run = record_counts()
first_run_diff = count_diff(before_first_run, after_first_run)

@coderabbitai coderabbitai Bot Jul 1, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

first_run_diff is computed but never asserted — first-run backfill behavior is unverified.

Per issue #8042's objective, the test should verify the command "creates or backfills missing migration records on the first run." first_run_diff (line 386) is dead code — nothing checks that expected records were actually created/backfilled by the first run. As written, the test would pass even if the first run silently did nothing.

💡 Example: assert something meaningful about first_run_diff
         after_first_run = record_counts()
         first_run_diff = count_diff(before_first_run, after_first_run)
+        self.assertTrue(
+            first_run_diff,
+            "First run should create or backfill expected migration records",
+        )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
before_first_run = record_counts()
self.run_key_migration_functions(
"fix_schema_config",
"fix_app_resource_dirs",
"fix_permissions",
"fix_business_rules",
"fix_tectonic_ranks",
"fix_misc",
)
after_first_run = record_counts()
first_run_diff = count_diff(before_first_run, after_first_run)
before_first_run = record_counts()
self.run_key_migration_functions(
"fix_schema_config",
"fix_app_resource_dirs",
"fix_permissions",
"fix_business_rules",
"fix_tectonic_ranks",
"fix_misc",
)
after_first_run = record_counts()
first_run_diff = count_diff(before_first_run, after_first_run)
self.assertTrue(
first_run_diff,
"First run should create or backfill expected migration records",
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@specifyweb/specify/management/commands/tests/test_run_key_migration_functions.py`
around lines 374 - 386, The first-run backfill behavior is not being verified
because first_run_diff is computed in the run_key_migration_functions test but
never asserted. Update this test to make a meaningful assertion about the
initial change in record_counts/count_diff after the first call to
run_key_migration_functions, using first_run_diff to confirm the expected
migration records were created or backfilled on the first run.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, something went wrong! Please try again later. 🐰 💔

Comment on lines +195 to +202
def test_reverse_hide_component_fields(self):
self.hidden_field.ishidden = True
self.hidden_field.save()

helper_0040_components.reverse_hide_component_fields(apps)

self.hidden_field.refresh_from_db()
self.assertTrue(self.hidden_field.ishidden)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the reverse_hide_component_fields implementation to confirm expected ishidden value.
rg -n -B2 -A15 "def reverse_hide_component_fields" specifyweb/specify/migration_utils/migration_helpers/helper_0040_components.py

Repository: specify/specify7

Length of output: 1072


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== implementation =="
sed -n '148,230p' specifyweb/specify/migration_utils/migration_helpers/helper_0040_components.py

echo
echo "== test context =="
sed -n '170,215p' specifyweb/specify/migration_utils/tests/test_helper_0040_components.py

echo
echo "== references to ishidden in this helper =="
rg -n "ishidden|reverse_hide_component_fields|hide_component_fields" specifyweb/specify/migration_utils/migration_helpers/helper_0040_components.py specifyweb/specify/migration_utils/tests/test_helper_0040_components.py

Repository: specify/specify7

Length of output: 4480


test_reverse_hide_component_fields should assert False
reverse_hide_component_fields updates matching items to ishidden=False, so this test’s final assertion is inverted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specifyweb/specify/migration_utils/tests/test_helper_0040_components.py`
around lines 195 - 202, The test_reverse_hide_component_fields assertion is
inverted: after calling reverse_hide_component_fields(apps), the hidden_field
should be verified as unhidden. Update the final assertion in
test_reverse_hide_component_fields so it checks the refreshed
self.hidden_field.ishidden is False, matching the behavior of
helper_0040_components.reverse_hide_component_fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Dev Attention Needed

2 participants