Skip to content

test: add ORM coverage for BelongsToMany and testing transaction utilities#69

Open
tmgbedu wants to merge 1 commit into
mainfrom
fix/model-update-bypasses-fillable-guard
Open

test: add ORM coverage for BelongsToMany and testing transaction utilities#69
tmgbedu wants to merge 1 commit into
mainfrom
fix/model-update-bypasses-fillable-guard

Conversation

@tmgbedu

@tmgbedu tmgbedu commented May 28, 2026

Copy link
Copy Markdown
Contributor

Rebased onto current main and trimmed to the genuinely net-new, green content.

What this PR adds

  • test_belongs_to_many.py — sqlite coverage for the BelongsToMany relationship: attach/detach, attach_related/detach_related, eager loading (incl. empty), pivot access, with_timestamps, explicit pivot table, and the query-has helpers.
  • testing/test_transaction.py — unit tests for the DatabaseTransaction / RefreshDatabase test-helper utilities (previously used by the test infra but never unit-tested).
  • Latent-gap fixes required by the above (existing relationship code already called these but they were undefined on main):
    • QueryBuilder.table() and QueryBuilder.without_global_scopes()
    • Attribute.delete_attribute()
    • BelongsToMany pivot attach/detach refactored to build pivot rows through the query builder directly.

Dropped since this branch was opened

  • The fillable-guard fix that named this branch has already landed on main (commits 82439510, 660698f8, a2d9f847, f2d82f03 are all ancestors of main) — nothing left to do there.
  • Duplicate post-processor tests — main already ships tests/masoniteorm/query/processors/test_post_processors.py (merged coverage PRs) covering the same four processor classes; the near-identical copy here was removed.
  • Morph relationship tests + source changes (MorphOne/MorphMany/MorphToMany) — these were written against the pre-Coverage: masoniteorm relationships (BelongsToMany, Morph*) #159 relationship internals and fail on current main. Making them pass requires completing the MorphOne/MorphToMany registry/descriptor migration that Coverage: masoniteorm relationships (BelongsToMany, Morph*) #159 applied to MorphMany only. That is a separate, reviewable change and is tracked as a follow-up rather than bundled here.

Gates

  • uv run pytest --ignore=tests/masoniteorm/postgres --cov1820 passed, 7 skipped, total coverage 79.65% (fail_under 68%).
  • ruff check + ruff format --check clean.
  • No coverage regression vs main (+29 tests).

…ities

Add sqlite tests for the BelongsToMany relationship (attach/detach,
attach_related/detach_related, eager loading, pivot access, timestamps,
explicit pivot table) and unit tests for the DatabaseTransaction /
RefreshDatabase testing helpers.

Support these paths by defining methods that existing relationship code
already depended on but were undefined:
- QueryBuilder.table() and QueryBuilder.without_global_scopes()
- Attribute.delete_attribute()
Refactor BelongsToMany pivot attach/detach to build pivot records through
the query builder directly.

The fillable-guard fix that originally motivated this branch already
landed on main. Duplicate post-processor tests (covered by the merged
query/processors suite) and the morph relationship tests/source changes
(which require a separate MorphOne/MorphToMany registry migration) were
dropped from this PR.
@tmgbedu tmgbedu force-pushed the fix/model-update-bypasses-fillable-guard branch from 48a0355 to 1113554 Compare July 11, 2026 19:40
@tmgbedu tmgbedu changed the title test: add ORM coverage for relationships, post-processors, and testing utilities test: add ORM coverage for BelongsToMany and testing transaction utilities Jul 11, 2026
@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@tmgbedu

tmgbedu commented Jul 12, 2026

Copy link
Copy Markdown
Contributor Author

Code review verdict: APPROVE (posting as comment — GitHub blocks self-approval on own PR).

APPROVE — review only (not merging).

Reproduced gates from fastapi_startkit/:

  • uv run pytest --ignore=tests/masoniteorm/postgres --cov1820 passed / 7 skipped, 79.65% (> 78.64% baseline). ✓
  • ruff check on all touched files → clean. ✓
  • Scope: exactly the 6 expected files (verified against real parent 9f01c543). ✓

Latent-bug fixes verified (methods main's BelongsToMany already calls but were undefined anywhere):

  1. Attribute.delete_attribute() — called in apply_query/get_related; grep confirms no definition on main. Impl pops from _attributes/_dirty_attributes with default=None → safe, minimal.
  2. QueryBuilder.table() — main calls Pivot.on(...).table(...) on a QueryBuilder; only DB/Schema/relationship had their own table, QueryBuilder did not. Sets _table, returns self. Correct.
  3. QueryBuilder.without_global_scopes() — main calls it; undefined on main. Resets _global_scopes = {} (same shape as __init__). Correct.

Pivot refactor (core relationship code) — acceptable risk:

  • Pivot storage moved from __original_attributes__ to _attributes[self._as] via Pivot() + set_raw_attributes(pivot_data, sync=True); __getattr__ reads _attributes, so product.pivot resolves.
  • attach/detach/attach_related/detach_related now build pivot rows via connection.query().table(...).insert()/.where().delete(), and get_pivot_table_name receives builders (which expose get_table_name()) rather than models. The old path was non-functional on main anyway (it hit the 3 undefined methods). Full suite + new BTM integration tests pass.

Tests: real sqlite integration with real assertions; net-new (main had zero BelongsToMany/transaction coverage → no duplication vs #147/#154-#161). Transaction unit tests mock DB wiring appropriately (assert_awaited_once), not hollow.

Minor (non-blocking): three shallow assertions — assertIsNotNone(pivot) (L55, L63) and assertIsNotNone(builder) (L121). L121 is near-tautological (builder is never None). They still exercise the real code paths (which would raise if broken), so not a blocker; consider asserting on pivot contents / timestamp keys and on the where_exists clause in a follow-up.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant