Skip to content

test(regression): add regression test for issue #2410#2549

Merged
ymc9 merged 1 commit intodevfrom
regression/issue-2410
Apr 3, 2026
Merged

test(regression): add regression test for issue #2410#2549
ymc9 merged 1 commit intodevfrom
regression/issue-2410

Conversation

@ymc9
Copy link
Copy Markdown
Member

@ymc9 ymc9 commented Apr 3, 2026

Summary

  • Adds a regression test for Invalid SQL generated when related models have @deny on identical field names #2410
  • Verifies that the PolicyPlugin generates valid SQL when a parent model (Thread) and a child model (Question) share an identical field name (apiKeyId) both protected by @deny('all', auth().role != 'ADMIN')
  • Tests that non-denied field updates succeed, denied field updates are rejected for non-admins, and allowed for admins

Test plan

  • TEST_DB_PROVIDER=sqlite vitest run test/issue-2410.test.ts passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Added regression test verifying that policy enforcement correctly handles related models with identically-named denied fields, ensuring proper role-based access control for nested record operations and field updates.

Verify that PolicyPlugin generates valid SQL when related models share
identical field names both protected by @deny rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude
Copy link
Copy Markdown
Contributor

claude bot commented Apr 3, 2026

Claude finished @ymc9's task —— View job


PR Review Complete ✅

Todo List

  • Read and analyze the regression test file
  • Review test structure and implementation quality
  • Check for potential bugs or issues
  • Evaluate test coverage and assertions
  • Provide constructive feedback

Code Review Feedback

This regression test for issue #2410 is well-structured and addresses the core issue effectively. The test verifies that PolicyPlugin generates valid SQL when parent and child models share identical field names with the same policy restrictions.

Strengths

  1. Clear Test Intent: The test title and comments clearly describe what issue is being tested
  2. Proper Setup: Uses createPolicyTestClient correctly for policy-enabled testing
  3. Realistic Schema: Models a real-world scenario with Thread and Question entities having shared field names
  4. Comprehensive Test Coverage: Tests three scenarios:
    • Non-denied field updates (should succeed for any user)
    • Denied field updates (should fail for non-admin)
    • Denied field updates (should succeed for admin)
  5. Consistent Test Patterns: Follows established regression test conventions used in other issue-*.test.ts files
  6. Proper Assertions: Uses appropriate vitest matchers (toResolveTruthy, toBeRejectedByPolicy)

📝 Minor Suggestions

  1. Test Isolation: Consider testing the Question model updates as well, since both models have the same field policy:
// Additional test case for Question model
await expect(
    db.$setAuth(user).question.update({
        where: { id: thread.questions[0].id },
        data: { apiKeyId: 'key-3' },
    }),
).toBeRejectedByPolicy();
  1. Edge Case Coverage: Consider adding a test that tries to update both models in a single transaction to ensure SQL generation handles multiple identical field names correctly

  2. Comment Enhancement: The schema comment could be more specific about the exact SQL generation issue:

// Tests that PolicyPlugin doesn't generate conflicting SQL aliases when 
// multiple models have identically named fields with the same @deny policies

🔍 Technical Analysis

  • Schema Design: The test schema correctly reproduces the problematic scenario - two related models with identical apiKeyId fields and identical policy expressions
  • Data Setup: Creates proper test data with nested creation using the questions.create syntax
  • Auth Testing: Properly tests both admin and non-admin user scenarios
  • Error Handling: Uses appropriate policy-specific assertion (toBeRejectedByPolicy)

🚀 Performance & Security

  • No performance concerns for a regression test
  • Test data is minimal and focused
  • No security issues - test properly isolates different user roles
  • Uses proper authentication context switching with $setAuth()

📊 Test Coverage Assessment

The test coverage is good for the specific issue but could be enhanced:

  • ✅ Tests the core SQL generation issue
  • ✅ Verifies policy enforcement works correctly
  • ✅ Tests both success and failure scenarios
  • ⚠️ Could add tests for the Question model specifically
  • ⚠️ Could test more complex scenarios (batch updates, nested updates)

📋 Recommendations

  1. Keep as-is: The current test effectively demonstrates the fix for issue Invalid SQL generated when related models have @deny on identical field names #2410
  2. Future enhancement: Consider adding the suggested Question model test if similar issues arise
  3. Documentation: The GitHub issue reference is helpful for context

Summary

This is a solid regression test that properly validates the fix for issue #2410. The test structure follows project conventions, uses appropriate testing utilities, and covers the essential scenarios. The code quality is excellent with clear intent and proper error handling.

Approval recommendation: ✅ Approved - This test effectively prevents regression of the SQL generation bug when models share identically named policy-protected fields.


@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

Added a regression test file verifying policy enforcement correctly handles multiple related models with identically-named @deny fields, testing update scenarios across admin and non-admin authentication contexts.

Changes

Cohort / File(s) Summary
Regression Test for Policy Enforcement
tests/regression/test/issue-2410.test.ts
New Vitest test validating policy enforcement with identically-named denied fields across related models (User, Thread, Question). Tests both allowed and rejected update scenarios for admin and non-admin roles.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop, a skip, a test so fine,
Where policies and queries align,
Admin rights and role-based views,
We check the paths SQL can't refuse!
Another regression caught and bound,
In tests, our safety's surely found! 🧪

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a regression test for issue #2410, which directly matches the changeset's single new test file.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch regression/issue-2410

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/regression/test/issue-2410.test.ts (1)

58-72: Consider extending coverage to also test the Question model's denied field.

The PR description states the issue involves both Thread.apiKeyId and Question.apiKeyId sharing identical @deny rules, but only Thread updates are verified. Testing Question.apiKeyId updates would strengthen confidence that the SQL generation fix handles both parent and child models correctly.

📝 Suggested additional assertions
         // updating a denied field should succeed for admin
         await expect(
             db.$setAuth(admin).thread.update({
                 where: { id: thread.id },
                 data: { apiKeyId: 'key-2' },
             }),
         ).toResolveTruthy();
+
+        // also verify the child model's denied field behaves correctly
+        const question = thread.questions?.[0] ?? (await db.$setAuth(admin).question.findFirst({ where: { threadId: thread.id } }));
+
+        // updating denied field on Question should be rejected for non-admin
+        await expect(
+            db.$setAuth(user).question.update({
+                where: { id: question.id },
+                data: { apiKeyId: 'key-3' },
+            }),
+        ).toBeRejectedByPolicy();
+
+        // updating denied field on Question should succeed for admin
+        await expect(
+            db.$setAuth(admin).question.update({
+                where: { id: question.id },
+                data: { apiKeyId: 'key-3' },
+            }),
+        ).toResolveTruthy();
     });
 });

Note: If the nested create doesn't return questions, you may need to include { include: { questions: true } } in the create call at line 40.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/regression/test/issue-2410.test.ts` around lines 58 - 72, Add
assertions mirroring the Thread.apiKeyId checks for the Question model: after
creating the thread with its questions (ensure the create includes { include: {
questions: true } } if questions are not returned), assert that a non-admin user
update of Question.apiKeyId via db.$setAuth(user).question.update({... where: {
id: question.id }, data: { apiKeyId: 'key-2' } }) is rejected by policy and that
the same update via db.$setAuth(admin).question.update(...) resolves truthily;
locate the Question update calls by the db.$setAuth(...).question.update and
question.id symbols to add these two expectations analogous to the Thread ones.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/regression/test/issue-2410.test.ts`:
- Around line 58-72: Add assertions mirroring the Thread.apiKeyId checks for the
Question model: after creating the thread with its questions (ensure the create
includes { include: { questions: true } } if questions are not returned), assert
that a non-admin user update of Question.apiKeyId via
db.$setAuth(user).question.update({... where: { id: question.id }, data: {
apiKeyId: 'key-2' } }) is rejected by policy and that the same update via
db.$setAuth(admin).question.update(...) resolves truthily; locate the Question
update calls by the db.$setAuth(...).question.update and question.id symbols to
add these two expectations analogous to the Thread ones.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 40a9881e-2bc3-423b-9ade-a1a7193db477

📥 Commits

Reviewing files that changed from the base of the PR and between c6c8ad1 and 50742fc.

📒 Files selected for processing (1)
  • tests/regression/test/issue-2410.test.ts

@ymc9 ymc9 merged commit a81d8f4 into dev Apr 3, 2026
9 checks passed
@ymc9 ymc9 deleted the regression/issue-2410 branch April 3, 2026 21:10
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