feat: add UI tests for CookieBanner and configure vitest for React#132
Conversation
✅ Deploy Preview for develop-devlovers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThis PR establishes frontend testing infrastructure by adding Vitest configuration, testing libraries, and a new CookieBanner component test suite. It also includes a database migration that adds a foreign key constraint and indexes to the quiz_attempts table. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @frontend/components/tests/CookieBanner.test.tsx:
- Around line 9-13: The hoisted vi.mock callback returns JSX but lacks the React
binding, causing failures under the mock's transform context; fix by importing
React into the test module scope (e.g., add import React from 'react' at the top
of the test) so the Link mock (the vi.mock(...) implementation that returns <a
href="#">{children}</a>) has React available for JSX, or alternatively rewrite
the mock to use React.createElement for the Link implementation.
In @frontend/vitest.config.ts:
- Around line 14-18: Update the Vitest test config so React component tests run
in a DOM-like environment: change the test configuration's environment property
in vitest.config.ts from 'node' to 'jsdom' (i.e., modify the test.environment
setting in the exported config object used by Vitest) so @testing-library/react
tests (e.g., CookieBanner) have access to document/window/localStorage.
🧹 Nitpick comments (4)
frontend/components/tests/CookieBanner.test.tsx (3)
1-3: Consider adding @testing-library/jest-dom for better assertions.The test uses
toBeDefined()andtoBeNull()which work but are less expressive than jest-dom matchers liketoBeInTheDocument(). Adding@testing-library/jest-domprovides more semantic DOM assertions.♻️ Recommended setup
- Install the package:
npm install -D @testing-library/jest-dom
- Create a setup file (e.g.,
vitest.setup.ts):import '@testing-library/jest-dom/vitest';
- Update
vitest.config.ts:test: { environment: 'jsdom', setupFiles: ['./vitest.setup.ts'], // ... }
29-38: Strengthen assertions with more specific matchers.
toBeDefined()passes for any truthy value. Consider usingtoBeInTheDocument()(with jest-dom) or at minimum check the element content/role for stronger validation.♻️ Suggested improvement
- expect(screen.getByText('title')).toBeDefined(); + expect(screen.getByText('title')).toBeVisible();Or without jest-dom:
- expect(screen.getByText('title')).toBeDefined(); + const titleElement = screen.getByText('title'); + expect(titleElement).toBeTruthy(); + expect(titleElement.textContent).toBe('title');
40-52: Good test coverage for the accept flow.The test properly verifies both the localStorage side effect and the UI state change after clicking accept.
Consider adding a test for the decline button to ensure complete coverage of the CookieBanner's interactive behavior.
📝 Additional test case suggestion
it('Click Decline -> Saves to LocalStorage -> Hides Banner', () => { render(<CookieBanner />); act(() => { vi.advanceTimersByTime(500); }); const declineButton = screen.getByText('decline'); fireEvent.click(declineButton); expect(localStorage.getItem('cookie-consent')).toBe('declined'); expect(screen.queryByText('title')).toBeNull(); });frontend/drizzle/0014_steep_kabuki.sql (1)
1-3: Verify no orphaneduser_idrecords exist before migration.Adding a foreign key constraint will fail if
quiz_attempts.user_idcontains values that don't exist inusers.id. Ensure data integrity before running this migration in production.Run this query against your database before applying the migration:
SELECT DISTINCT qa.user_id FROM quiz_attempts qa LEFT JOIN users u ON qa.user_id = u.id WHERE u.id IS NULL;If any rows are returned, either:
- Delete the orphaned records, or
- Create placeholder user records
Also consider running the migration during low-traffic periods as creating indexes on large tables can lock the table temporarily.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
frontend/components/tests/CookieBanner.test.tsxfrontend/drizzle/0014_steep_kabuki.sqlfrontend/drizzle/meta/0014_snapshot.jsonfrontend/drizzle/meta/_journal.jsonfrontend/package.jsonfrontend/vitest.config.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-12-30T16:01:02.523Z
Learnt from: kryvosheyin
Repo: DevLoversTeam/devlovers.net PR: 88
File: frontend/drizzle/schema.ts:153-153
Timestamp: 2025-12-30T16:01:02.523Z
Learning: The file frontend/drizzle/schema.ts is a legacy file not used by Drizzle or the runtime. The canonical schemas live in frontend/db/schema/* as configured in drizzle-config.ts, and that's what migrations and runtime use.
Applied to files:
frontend/drizzle/meta/0014_snapshot.json
🧬 Code graph analysis (2)
frontend/vitest.config.ts (1)
frontend/save-structure.cjs (1)
path(2-2)
frontend/components/tests/CookieBanner.test.tsx (1)
frontend/components/shared/CookieBanner.tsx (1)
CookieBanner(9-91)
🔇 Additional comments (5)
frontend/package.json (2)
16-19: LGTM! Test scripts are well-structured.The test scripts follow standard Vitest conventions:
testfor watch mode,test:uifor the interactive UI, andtest:runfor CI/single-run execution.
57-59: Testing dependencies are appropriate for React 19.The @testing-library/react v16.3.1 is compatible with React 19, and jsdom v27.4.0 provides the browser environment for component tests.
Also applies to: 67-67
frontend/vitest.config.ts (1)
16-16: Test include patterns look correct.The glob patterns appropriately separate
.test.tsfor lib tests (node environment) and.test.tsxfor component tests (DOM environment). However, if you need different environments for different test types, consider using Vitest'senvironmentMatchGlobsoption.If you need to keep
nodeenvironment forlib/tests, you can configure per-pattern environments:test: { environment: 'node', environmentMatchGlobs: [ ['components/tests/**/*.test.tsx', 'jsdom'], ], include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'], globals: true, },frontend/drizzle/meta/_journal.json (1)
103-109: LGTM!The journal entry correctly registers the new migration with the expected format and sequence.
frontend/drizzle/meta/0014_snapshot.json (1)
1-2333: LGTM! Auto-generated schema snapshot.This snapshot is generated by Drizzle and correctly reflects the schema state after applying migration 0014. The new FK constraint and indexes on
quiz_attemptsare properly captured.
| vi.mock('@/i18n/routing', () => ({ | ||
| Link: ({ children }: { children: React.ReactNode }) => ( | ||
| <a href="#">{children}</a> | ||
| ), | ||
| })); |
There was a problem hiding this comment.
Add React import for JSX in the mock.
The Link mock returns JSX but doesn't import React. While React 17+ automatic JSX transform handles this in regular files, hoisted vi.mock calls may not have access to the transform context.
🐛 Proposed fix
+import React from 'react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, act, fireEvent } from '@testing-library/react';
import { CookieBanner } from '@/components/shared/CookieBanner';📝 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.
| vi.mock('@/i18n/routing', () => ({ | |
| Link: ({ children }: { children: React.ReactNode }) => ( | |
| <a href="#">{children}</a> | |
| ), | |
| })); | |
| import React from 'react'; | |
| import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; | |
| import { render, screen, act, fireEvent } from '@testing-library/react'; | |
| import { CookieBanner } from '@/components/shared/CookieBanner'; | |
| vi.mock('@/i18n/routing', () => ({ | |
| Link: ({ children }: { children: React.ReactNode }) => ( | |
| <a href="#">{children}</a> | |
| ), | |
| })); |
🤖 Prompt for AI Agents
In @frontend/components/tests/CookieBanner.test.tsx around lines 9 - 13, The
hoisted vi.mock callback returns JSX but lacks the React binding, causing
failures under the mock's transform context; fix by importing React into the
test module scope (e.g., add import React from 'react' at the top of the test)
so the Link mock (the vi.mock(...) implementation that returns <a
href="#">{children}</a>) has React available for JSX, or alternatively rewrite
the mock to use React.createElement for the Link implementation.
| test: { | ||
| environment: "node", | ||
| include: ["lib/tests/**/*.test.ts"], | ||
| environment: 'node', | ||
| include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'], | ||
| globals: true, | ||
| }, |
There was a problem hiding this comment.
Environment should be jsdom for React component tests.
The test environment is set to 'node', but the CookieBanner tests use @testing-library/react which requires DOM APIs (document, window, localStorage). Since jsdom is already added as a devDependency, update the environment accordingly.
🐛 Proposed fix
test: {
- environment: 'node',
+ environment: 'jsdom',
include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'],
globals: true,
},📝 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.
| test: { | |
| environment: "node", | |
| include: ["lib/tests/**/*.test.ts"], | |
| environment: 'node', | |
| include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'], | |
| globals: true, | |
| }, | |
| test: { | |
| environment: 'jsdom', | |
| include: ['lib/tests/**/*.test.ts', 'components/tests/**/*.test.tsx'], | |
| globals: true, | |
| }, |
🤖 Prompt for AI Agents
In @frontend/vitest.config.ts around lines 14 - 18, Update the Vitest test
config so React component tests run in a DOM-like environment: change the test
configuration's environment property in vitest.config.ts from 'node' to 'jsdom'
(i.e., modify the test.environment setting in the exported config object used by
Vitest) so @testing-library/react tests (e.g., CookieBanner) have access to
document/window/localStorage.
Summary by CodeRabbit
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.