Skip to content

feat: add userId to form controllers, refactor template route structu… - #84

Merged
Basharkhan7776 merged 2 commits into
Openlabsops:mainfrom
silky-x0:test/index-auth-routes
Jul 6, 2026
Merged

Basharkhan7776 merged 2 commits into
Openlabsops:mainfrom
silky-x0:test/index-auth-routes

Conversation

@silky-x0

@silky-x0 silky-x0 commented Jul 6, 2026 •

Copy link
Copy Markdown
Collaborator

Fix: Index & Auth Route Integration Tests

Description

Closes #50

Added integration tests to ensure the reliability of the index and authentication routing flows.

Changes Made

  • Added a test case to verify that a direct GET call to the OAuth initiation route returns the proper redirect URL.
  • Added a test case to simulate a successful Better-Auth callback, validating that a session token is successfully established.
  • Added integration coverage for the sign-in flow so direct OAuth entry points and the Better-Auth callback are verified end to end.
  • Confirmed that a successful social login now creates a session and carries users through the expected auth flow.
  • Improved form responses by including the form owner identifier in returned data.
  • Simplified the community templates endpoint to return a cleaner template list and metadata.
  • Added test cleanup to disconnect the database more reliably after integration runs.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@silky-x0, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2c269f9b-81f4-4dc6-88e6-48d8f495f4fb

📥 Commits

Reviewing files that changed from the base of the PR and between 4810894 and b8d2b76.

📒 Files selected for processing (2)
  • apps/api/src/controllers/template.controller.ts
  • packages/api-tests/integration-tests/modules/auth.test.ts
📝 Walkthrough

Walkthrough

This PR adds a Bun-based OAuth integration test suite mocking GitHub auth flows, adds prisma disconnect cleanup in test bootstrap, includes userId in form controller select projections, simplifies getCommunityTemplates by removing nested reviews from the response, and adds a .gitignore rule for log files.

Changes

Backend and test changes

Layer / File(s) Summary
OAuth integration test suite
packages/api-tests/integration-tests/modules/auth.test.ts
Adds a test suite mocking fetch for GitHub OAuth, verifying redirect URL/state, session cookie establishment, and onboarding/dashboard redirect behavior.
Test bootstrap prisma disconnect
packages/api-tests/integration-tests/setup/bootstrap.ts
Adds try/catch prisma $disconnect() with logging in afterAll.
Form controller userId selection
apps/api/src/controllers/form.controller.ts
Adds userId to Prisma select in createForm, getForm, and updateForm.
Community templates response simplification
apps/api/src/controllers/template.controller.ts
Removes nested paginated reviews from getCommunityTemplates response and derives pagination meta from template count.
Gitignore log file rule
.gitignore
Adds a # logs section and *.log pattern.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Test as "Test Suite"
  participant API as "OAuth Initiation Route"
  participant BetterAuth as "Better-Auth Callback"
  participant DB as "Database"

  Test->>API: initiate social auth
  API-->>Test: redirect URL + state + better-auth.state cookie
  Test->>BetterAuth: call callback with mocked GitHub responses
  BetterAuth->>DB: create/update user
  BetterAuth-->>Test: better-auth.session_token cookie
  Test->>API: custom OAuth callback (new user)
  API-->>Test: redirect to /onboarding
  Test->>DB: set username
  Test->>API: custom OAuth callback again
  API-->>Test: redirect to /dashboard
Loading

Possibly related PRs

  • Openlabsops/Snap-form#57: Shares the same Bun integration testing suite work, including the OAuth auth test and bootstrap prisma disconnect cleanup.
  • Openlabsops/Snap-form#80: Both PRs modify getCommunityTemplates in template.controller.ts, with this PR further changing its response shape by dropping nested reviews.

Poem

A rabbit hops through logs and tests,
With OAuth flows put through their quests,
userId now rides along the form,
Reviews trimmed down to a leaner norm,
*.log tucked away, out of sight — 🐇✨
Hop hop, ship it, all feels right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR also changes .gitignore, form/template controllers, and test bootstrap, which are unrelated to the auth routing tests. Split the unrelated .gitignore, controller, and bootstrap changes into separate PRs or revert them so this PR stays focused on issue #50.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title mentions real parts of the change, but it does not emphasize the main auth integration test work.
Linked Issues check ✅ Passed The new OAuth integration tests cover both the initiation redirect and the Better-Auth callback session token flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/api/src/controllers/form.controller.ts (1)

92-97: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Correct change, but consider deduplicating the repeated select shape.

Adding userId: true is correct and matches the test expectation that response.data.data.userId equals the authenticated user's id, and since routes are guarded by requireAuth plus where: { id, userId } filters, no cross-user data is exposed. However, the identical select object is now duplicated three times (createForm, getForm, updateForm); extracting it once avoids the fields drifting out of sync in the future (e.g. Line 129 already has a stray trailing space vs. the other two).

♻️ Proposed refactor: extract shared select object
+const formSelect = {
+  id: true, title: true, description: true, iconSymbol: true,
+  coverUrl: true, published: true, slug: true, type: true,
+  requireEmail: true, responseCount: true, viewCount: true,
+  fields: true, createdAt: true, updatedAt: true, userId: true,
+} as const;
+
 export const createForm: RequestHandler = asyncHandler(
   async (req: Request, res: Response) => {
     ...
     const form = await prisma.form.create({
       data: { ... },
-      select: {
-        id: true, title: true, description: true, iconSymbol: true,
-        coverUrl: true, published: true, slug: true, type: true,
-        requireEmail: true, responseCount: true, viewCount: true,
-        fields: true, createdAt: true, updatedAt: true, userId: true,
-      },
+      select: formSelect,
     });

Apply the same select: formSelect substitution in getForm and updateForm.

Also applies to: 125-131, 201-206

🤖 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 `@apps/api/src/controllers/form.controller.ts` around lines 92 - 97, The
`select` shape in `createForm`, `getForm`, and `updateForm` is duplicated and
should be centralized to keep the returned form fields consistent. Extract the
repeated object into a shared `formSelect` constant in `FormController`, then
replace each inline `select` with `formSelect` in those methods so future field
changes only need to be made in one place.
🤖 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 `@apps/api/src/controllers/template.controller.ts`:
- Around line 289-298: The pagination response shape in getCommunityTemplates is
inconsistent with the sibling template endpoint because it uses meta instead of
pagination. Update the response object in template.controller so
getCommunityTemplates returns the same pagination key name as getTemplateById,
keeping the API contract consistent across both handlers.

In `@packages/api-tests/integration-tests/modules/auth.test.ts`:
- Around line 7-11: Replace the manual globalThis.fetch capture and
__originalFetch flag with bun:test’s native mocking APIs in auth.test.ts. Update
the fetch setup around the existing originalFetch usage to use spyOn(globalThis,
"fetch") with mockImplementation and mockRestore instead of mutating a global
sentinel, and apply the same pattern throughout the affected auth test cases so
mocking/restoration is handled by bun:test rather than module-load ordering.
- Around line 70-91: The test description and request type are inconsistent: the
inline note says a direct GET call, but auth initiation is currently exercised
with client.post on the social sign-in flow. Update the test in auth.test.ts so
it matches the intended behavior by either changing the comment to describe the
POST JSON flow or, if the acceptance criteria require it, switching to the
actual GET-based initiation route and validating the redirect URL there. Use the
existing test block around the sign-in/social request and the redirectUrl/state
assertions to keep the intent clear.

---

Outside diff comments:
In `@apps/api/src/controllers/form.controller.ts`:
- Around line 92-97: The `select` shape in `createForm`, `getForm`, and
`updateForm` is duplicated and should be centralized to keep the returned form
fields consistent. Extract the repeated object into a shared `formSelect`
constant in `FormController`, then replace each inline `select` with
`formSelect` in those methods so future field changes only need to be made in
one place.
🪄 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: ASSERTIVE

Plan: Pro Plus

Run ID: 33cb3404-29aa-47e7-a649-4a8bb376d587

📥 Commits

Reviewing files that changed from the base of the PR and between 3f38c09 and 4810894.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • .gitignore
  • apps/api/src/controllers/form.controller.ts
  • apps/api/src/controllers/template.controller.ts
  • packages/api-tests/integration-tests/modules/auth.test.ts
  • packages/api-tests/integration-tests/setup/bootstrap.ts
📜 Review details
🔇 Additional comments (6)
.gitignore (1)

42-43: LGTM!

apps/api/src/controllers/template.controller.ts (2)

152-152: LGTM!

Also applies to: 499-501


263-284: 🗄️ Data Integrity & Integration

Confirm no client relies on rating data from GET /api/v1/templates/community. This response now returns only template summary fields; any UI or integration expecting reviews, avgStars, or reviewCount will need a separate endpoint or expanded payload.

packages/api-tests/integration-tests/modules/auth.test.ts (2)

137-143: 🎯 Functional Correctness | ⚡ Quick win

Inconsistent header usage vs. earlier requests in the same flow.

Lines 75-79 and 105-109 spoof Host/X-Forwarded-Host/X-Forwarded-Proto: localhost:3000, but the custom callback requests here omit these headers entirely. If the app route relies on forwarded headers to resolve the correct base URL for the onboarding/dashboard redirect target (as it apparently does for the better-auth callback), omitting them here could produce flaky or environment-dependent redirect assertions.

Also applies to: 156-162


1-167: 🩺 Stability & Availability

No change needed. globalThis.fetch is shared with the in-process test server, so the GitHub calls will hit this mock.

packages/api-tests/integration-tests/setup/bootstrap.ts (1)

36-43: LGTM!

Comment thread apps/api/src/controllers/template.controller.ts
Comment thread packages/api-tests/integration-tests/modules/auth.test.ts Outdated
Comment thread packages/api-tests/integration-tests/modules/auth.test.ts Outdated
…o pagination in template controller response

@Basharkhan7776 Basharkhan7776 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it should give me the link on terminal to login in then store token as const use that session for further testing. What do you think?

@silky-x0

silky-x0 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

Since these are automated integration tests designed to run in our CI/CD pipeline, they need to run headlessly without human intervention. Pausing the terminal to wait for a manual browser login would cause our CI pipelines ( GitHub Actions) to hang and fail. Instead, I've mocked the external GitHub OAuth HTTP calls and simulated the callback flow. This ensures the tests are fast, deterministic, and can run completely autonomously while still fully exercising our backend's session creation logic.

@Basharkhan7776

Copy link
Copy Markdown
Member

Okay I understood, but the direct fetching testing is better to analyze the problems and second thing is that if we test any model then we push. In production we have 2 environment 1st is production(main) and development for testing, we won't deploy every PR, we test the stability then go to main.

Also issue is about to make a direct call in testing.

@silky-x0

silky-x0 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator Author

I completely agree that testing real, direct calls is the best way to ensure stability before deploying to development/main!

Just to clarify how the tests are currently set up:

  1. For our own routes (like Onboarding): We are making direct network calls. The test helper uses axios to make real POST requests to our /register and /login endpoints against the live test server to retrieve a real session token. It doesn't mock our database or our auth logic.

  2. For the GitHub OAuth route specifically: Beacuse GitHub's OAuth flow requires rendering an HTML page and manual human interaction (clicking "Authorize"), we can't fully automate a direct HTTP call to GitHub without using a browser automation tool like Playwright. That's why the external GitHub api call is mocked, but the actual routing, session creation, and database logic on our end is fully tested via direct calls.

If the goal of the issue was to create a script for manual QA testing in the terminal (where a developer clicks a link, logs in, and the terminal captures the token), I can definitely write a separate Node CLI script for that! But for the automated CI test suite, we have to keep it headless. Let me know which direction you'd prefer, also if necessary we can create issue for that.

@Basharkhan7776
Basharkhan7776 merged commit 68ab888 into Openlabsops:main Jul 6, 2026
3 checks passed
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.

[Test] Index & Auth Routes

2 participants