(SP: 3) [Testing] Vitest config + unit + integration tests for quiz module#204
Conversation
…(issues #181, #193, #194) - Refactor QaTabButton to shared CategoryTabButton component - Add category accent colors to QuizCard, buttons, progress indicators - Standardize colors with CSS variables, traffic light timer - Add DynamicGridBackground to quizzes list page - Border-only answer feedback, semi-transparent progress styles
Changed violationsCount > 3 to >= 3 in QuizResult points block to match the warning banner threshold at line 124.
- Configure Vitest for quiz module - Add test factories and setup utilities - Add quiz-crypto tests (13 tests) - Add quiz-session tests (12 tests)
…eat hook (#199) - verify-answer.test.ts: 8 tests for API endpoint - Correct/wrong answer verification - Validation errors (missing fields, tampered data) - Security: rejects modified encrypted answers - quiz-anticheat.test.ts: 10 tests for useAntiCheat hook - Detects copy, paste, context-menu, tab-switch events - Respects isActive flag - Reset and cleanup functionality Total quiz tests: 52 (9 setup + 25 unit + 18 integration)
✅ Deploy Preview for develop-devlovers ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughAdds comprehensive quiz testing infrastructure: test factories, test environment utilities, vitest coverage config and devDependency, and ~13 new test files covering crypto, session persistence, anti-cheat, hooks, API routes, storage helpers, and a UI flow test. Changes
Sequence Diagram(s)(Skipped — changes are test additions and utilities; no new multi-component runtime control flow introduced that requires diagramming.) Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/package.json (1)
67-77: Fix peer dependency mismatch:@vitest/coverage-v8@4.0.18 requires vitest@4.0.18.
@vitest/coverage-v8declares pinned peer dependencies (exact version match). The current setup violates this:@vitest/coverage-v8@4.0.18expectsvitest@4.0.18, not4.0.16.Choose one:
- Downgrade
@vitest/coverage-v8to^4.0.16to match vitest- Upgrade
vitestto^4.0.18to match the coverage packageOption 1: Downgrade coverage package
- "@vitest/coverage-v8": "^4.0.18", + "@vitest/coverage-v8": "^4.0.16",Option 2: Upgrade vitest
- "vitest": "^4.0.16" + "vitest": "^4.0.18"
🤖 Fix all issues with AI agents
In `@frontend/lib/tests/quiz/setup.ts`:
- Around line 7-8: Replace the hardcoded high-entropy TEST_ENCRYPTION_KEY value
with a clearly labeled low-entropy test key (e.g., "test-key-000") or add a
Gitleaks allowlist comment immediately above TEST_ENCRYPTION_KEY to mark it as a
non-secret test artifact; update the exported constant TEST_ENCRYPTION_KEY in
frontend/lib/tests/quiz/setup.ts accordingly and ensure the comment states it's
intentionally non-sensitive for tests so static scanners will ignore it.
🧹 Nitpick comments (7)
frontend/lib/tests/quiz/setup.ts (1)
14-24: Restore prior QUIZ_ENCRYPTION_KEY after tests.
Current cleanup deletes any preexisting value, which can break other suites.♻️ Preserve and restore prior env value
+let previousQuizEncryptionKey: string | undefined; + export function setupQuizTestEnv(): void { - process.env.QUIZ_ENCRYPTION_KEY = TEST_ENCRYPTION_KEY; + previousQuizEncryptionKey = process.env.QUIZ_ENCRYPTION_KEY; + process.env.QUIZ_ENCRYPTION_KEY = TEST_ENCRYPTION_KEY; } export function cleanupQuizTestEnv(): void { - delete process.env.QUIZ_ENCRYPTION_KEY; + if (typeof previousQuizEncryptionKey === 'undefined') { + delete process.env.QUIZ_ENCRYPTION_KEY; + } else { + process.env.QUIZ_ENCRYPTION_KEY = previousQuizEncryptionKey; + } + previousQuizEncryptionKey = undefined; }frontend/lib/tests/factories/quiz/quiz.ts (1)
65-71: Use a single timestamp for deterministic sessions.
Minor, but helps avoid flaky assertions if tests compare fields.♻️ Suggested change
export function createMockQuizSession( overrides?: Partial<MockQuizSession> ): MockQuizSession { + const now = Date.now(); return { status: 'in_progress', currentIndex: 0, answers: [], questionStatus: 'answering', selectedAnswerId: null, - startedAt: Date.now(), - savedAt: Date.now(), + startedAt: now, + savedAt: now, ...overrides, }; }frontend/lib/tests/quiz/quiz-anticheat.test.ts (3)
75-99: Consider adding a test for tab becoming visible again.The test verifies
isTabActivebecomesfalsewhen the tab is hidden, but there's no test verifying it returns totruewhen the tab becomes visible again. This would complete the visibility change coverage.📝 Suggested additional test case
it('sets isTabActive back to true when tab becomes visible', () => { const { result } = renderHook(() => useAntiCheat(true)); // Hide tab Object.defineProperty(document, 'hidden', { value: true, writable: true, configurable: true }); act(() => { document.dispatchEvent(new Event('visibilitychange')); }); expect(result.current.isTabActive).toBe(false); // Show tab Object.defineProperty(document, 'hidden', { value: false, writable: true, configurable: true }); act(() => { document.dispatchEvent(new Event('visibilitychange')); }); expect(result.current.isTabActive).toBe(true); });
113-125: Consider verifyingshowWarningresets after timeout.The test verifies
showWarningbecomestrueon violation, but doesn't verify it returns tofalseafter the 3000ms timeout. Since fake timers are already set up, this would be straightforward to add.📝 Suggested enhancement
it('sets showWarning to true when violation occurs', () => { const { result } = renderHook(() => useAntiCheat(true)); expect(result.current.showWarning).toBe(false); act(() => { document.dispatchEvent(new Event('copy')); }); expect(result.current.showWarning).toBe(true); + + act(() => { + vi.advanceTimersByTime(3000); + }); + + expect(result.current.showWarning).toBe(false); }); -
51-61: Minor: Consider consistent toast verification across event tests.The copy event test (line 48) verifies
toast.warningwas called with the expected message, but the paste and context-menu tests don't include this verification. Consider adding toast assertions for consistency, or removing from the copy test if comprehensive toast coverage isn't needed.frontend/lib/tests/quiz/verify-answer.test.ts (2)
55-74: Consider making wrong answer selection more robust.Line 61 assumes
questions[0].answers[1]is always wrong, which depends on the factory implementation detail that the correct answer is at index 0. This could break silently if the factory changes.📝 More robust wrong answer selection
it('returns isCorrect: false for wrong answer', async () => { const questions = createMockQuestions(3); const correctAnswersMap = createCorrectAnswersMap(questions); const encryptedAnswers = encryptAnswers(correctAnswersMap); const questionId = questions[0].id; - const wrongAnswerId = questions[0].answers[1].id; // second answer is wrong + const correctAnswerId = correctAnswersMap[questionId]; + const wrongAnswer = questions[0].answers.find(a => a.id !== correctAnswerId); + const wrongAnswerId = wrongAnswer!.id; const request = createVerifyRequest({ questionId, answerId: wrongAnswerId, encryptedAnswers, });
95-108: Consider adding error message assertion.The test for missing
answerIdonly checks the status code but doesn't verify the error message like thequestionIdtest does (line 92). Consider adding the assertion for consistency.📝 Suggested enhancement
const response = await POST(request); + const data = await response.json(); expect(response.status).toBe(400); + expect(data.error).toBe('Missing required fields'); });
| export const TEST_ENCRYPTION_KEY = | ||
| 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2'; |
There was a problem hiding this comment.
Gitleaks likely to fail on hardcoded key.
Static analysis already flagged this; CI may block. Use an allowlist comment or a low‑entropy test key.
✅ Safer test key (low‑entropy)
-export const TEST_ENCRYPTION_KEY =
- 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2';
+export const TEST_ENCRYPTION_KEY =
+ '0000000000000000000000000000000000000000000000000000000000000000';📝 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.
| export const TEST_ENCRYPTION_KEY = | |
| 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2'; | |
| export const TEST_ENCRYPTION_KEY = | |
| '0000000000000000000000000000000000000000000000000000000000000000'; |
🧰 Tools
🪛 Gitleaks (8.30.0)
[high] 7-8: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In `@frontend/lib/tests/quiz/setup.ts` around lines 7 - 8, Replace the hardcoded
high-entropy TEST_ENCRYPTION_KEY value with a clearly labeled low-entropy test
key (e.g., "test-key-000") or add a Gitleaks allowlist comment immediately above
TEST_ENCRYPTION_KEY to mark it as a non-secret test artifact; update the
exported constant TEST_ENCRYPTION_KEY in frontend/lib/tests/quiz/setup.ts
accordingly and ensure the comment states it's intentionally non-sensitive for
tests so static scanners will ignore it.
…UI flow Add 28 new tests covering: - useQuizSession hook (6 tests) - useQuizGuards hook (8 tests) - guest-quiz storage (5 tests) - guest-result API route (5 tests) - quiz-slug API route (3 tests) - QuizContainer UI flow (1 test) Coverage: 35% -> 90.94% (quiz scope) Tests: 52 -> 80
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In `@frontend/coverage-quiz/app/api/quiz/guest-result/index.html`:
- Around line 1-116: Remove the committed Istanbul-generated coverage HTML
(app/api/quiz/guest-result/index.html) and other generated coverage directories,
add an appropriate ignore rule like coverage-quiz/ or **/coverage*/ to
.gitignore, commit the removal and updated .gitignore, and (optionally) wire
coverage reporting into CI (e.g., Codecov/Coveralls) instead of committing
coverage artifacts.
In `@frontend/coverage-quiz/base.css`:
- Around line 5-9: The CSS for the body selector contains duplicate font names
and redundant properties causing Biome duplicate-property warnings; update the
body rule in base.css (the "body" selector) to use a deduplicated, standardized
font-family string (e.g., remove repeated entries so only "Helvetica Neue,
Helvetica, Arial, sans-serif" remains) and remove or consolidate any repeated
properties (like duplicate color or font-size declarations) elsewhere in the
file (also check the other affected blocks around lines referenced) so each
property appears only once per selector or exclude coverage-quiz/** from linting
if these are generated assets.
In `@frontend/coverage-quiz/block-navigation.js`:
- Around line 24-29: toggleClass currently calls
missingCoverageElements.item(currentIndex).classList.remove(...) but
currentIndex can be undefined on first navigation, causing a null reference;
update toggleClass (and/or initialization of currentIndex) to guard the removal
by checking that missingCoverageElements.item(currentIndex) is non-null before
calling .classList.remove, then perform the .classList.add on
missingCoverageElements.item(index) and set currentIndex = index; alternatively
ensure currentIndex is initialized to a valid integer before toggleClass is ever
invoked. Use the function name toggleClass and the variables currentIndex and
missingCoverageElements.item(...) to locate and apply the guard.
- Around line 41-63: Both navigation functions (goToPrevious and goToNext) call
makeCurrent(0) when missingCoverageElements is empty, which leads to makeCurrent
attempting to access missingCoverageElements.item(0) and crashing; fix by adding
an early guard in each function (or a shared check before navigation) that
returns immediately if missingCoverageElements.length === 0 so makeCurrent is
never called on an empty list, leaving existing index logic unchanged.
In `@frontend/lib/tests/quiz/use-quiz-guards.test.ts`:
- Around line 148-160: The test's final assertion is not being invoked because
the matcher is referenced as a property; in the test using useQuizGuards(),
replace the incorrect ".toBeNull" with a call ".toBeNull()" so the assertion
runs; update the assertion that checks
sessionStorage.getItem(getQuizReloadKey(params.quizId)) in the test that calls
result.current.markQuitting() to use .toBeNull() (referencing getQuizReloadKey,
useQuizGuards, and markQuitting to locate the test).
♻️ Duplicate comments (7)
frontend/coverage-quiz/app/api/quiz/verify-answer/index.html (1)
1-116: Auto-generated coverage file — same concern as above.This file should be excluded from version control along with the rest of the
coverage-quiz/directory.frontend/coverage-quiz/app/api/quiz/[slug]/index.html (1)
1-116: Auto-generated coverage file — same concern as above.This file should be excluded from version control along with the rest of the
coverage-quiz/directory.frontend/coverage-quiz/hooks/index.html (1)
1-131: Auto-generated coverage file — same concern as above.This file should be excluded from version control along with the rest of the
coverage-quiz/directory.frontend/coverage-quiz/lib/quiz/guest-quiz.ts.html (1)
1-244: Auto-generated coverage file — same concern as above.This file should be excluded from version control along with the rest of the
coverage-quiz/directory. Note that this file also embeds source code, making it redundant with the actual source files.frontend/coverage-quiz/hooks/useQuizGuards.ts.html (1)
1-430: Auto-generated coverage file — same concern as above.This file should be excluded from version control along with the rest of the
coverage-quiz/directory.frontend/coverage-quiz/lib/quiz/quiz-session.ts.html (1)
1-283: Auto-generated coverage report - same concern as other coverage files.This is another Istanbul coverage artifact that should not be committed. See the comment on
quiz-crypto.ts.htmlfor details.frontend/coverage-quiz/hooks/useQuizSession.ts.html (1)
1-313: Auto-generated coverage report - same concern as other coverage files.This is another Istanbul coverage artifact that should not be committed. See the comment on
quiz-crypto.ts.htmlfor details.
🧹 Nitpick comments (9)
frontend/vitest.config.ts (1)
16-22: Consider addingcomponents/quizsource files to the coverage configuration with explicit file extensions.UI tests are configured to run under
components/quiz/tests, butcoverage.includecurrently omits those component source files, so coverage metrics won't be collected for them. Additionally, Vitest v4 recommends including file extensions in coverage globs for clarity and to avoid inadvertently capturing non-source files.✅ Suggested update
coverage: { provider: 'v8', reporter: ['text', 'html'], - include: ['lib/quiz/**', 'hooks/**', 'app/api/quiz/**'], + include: ['lib/quiz/**/*.ts', 'hooks/**/*.ts', 'app/api/quiz/**/*.ts', 'components/quiz/**/*.tsx'], },frontend/coverage-quiz/block-navigation.js (1)
74-84:event.whichis deprecated.
event.whichis deprecated in favor ofevent.key. Consider updating for better compatibility with modern browsers.♻️ Suggested refactor using event.key
-switch (event.which) { - case 78: // n - case 74: // j - goToNext(); - break; - case 66: // b - case 75: // k - case 80: // p - goToPrevious(); - break; -} +switch (event.key.toLowerCase()) { + case 'n': + case 'j': + goToNext(); + break; + case 'b': + case 'k': + case 'p': + goToPrevious(); + break; +}frontend/coverage-quiz/sorter.js (2)
84-86: Consider using DOM methods instead of innerHTML concatenation.While this code operates on trusted Istanbul-generated content, using
innerHTMLconcatenation can be a code smell. A safer pattern uses DOM methods.♻️ Safer alternative using DOM methods
if (col.sortable) { col.defaultDescSort = col.type === 'number'; - colNode.innerHTML = - colNode.innerHTML + '<span class="sorter"></span>'; + var sorterSpan = document.createElement('span'); + sorterSpan.className = 'sorter'; + colNode.appendChild(sorterSpan); }
189-193: Legacy IE compatibility check may be unnecessary.The
attachEventfallback (line 192) is for IE8 and earlier, which are no longer supported by modern tooling. If IE8 support is not required, this can be simplified.♻️ Simplified without IE8 fallback
-if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); -} else { - el.attachEvent('onclick', ithSorter(i)); -} +el.addEventListener('click', ithSorter(i));frontend/coverage-quiz/index.html (1)
167-171:window.onloadassignment may conflict with other scripts.Direct assignment to
window.onloadoverwrites any previously assigned handlers. Sincesorter.jsusesaddEventListener('load', ...), there's no conflict in this specific case, but this pattern can cause issues if scripts are reordered.♻️ Safer pattern using addEventListener
-<script> - window.onload = function () { - prettyPrint(); - }; -</script> +<script> + window.addEventListener('load', function () { + prettyPrint(); + }); +</script>frontend/coverage-quiz/app/api/quiz/verify-answer/route.ts.html (1)
1-232: Coverage HTML artifacts should not be committed to the repository.These auto-generated Istanbul coverage reports are currently tracked in
frontend/coverage-quiz/, even though.gitignorehas a/coveragerule at the root level (which doesn't match thefrontend/coverage-quiz/subdirectory). Coverage artifacts typically should be:
- Generated during CI/CD and published as build artifacts
- Uploaded to a coverage service (Codecov, Coveralls, etc.)
- Added to
.gitignoreto prevent bloating the repositoryConsider either adding
frontend/coverage-quiz/to.gitignoreor removing this directory if it was committed unintentionally. Alternatively, generate these reports dynamically via a coverage reporting service instead of committing them.frontend/lib/tests/quiz/use-quiz-guards.test.ts (1)
64-83: Consider using a more realistic external URL for clarity.The test uses
javascript:void(0)as the external link href. While this technically works (it doesn't contain the current pathname), using a realistic external URL likehttps://example.comwould make the test's intent clearer and better represent real-world scenarios.Suggested improvement
- link.setAttribute('href', 'javascript:void(0)'); + link.setAttribute('href', 'https://example.com');frontend/lib/tests/quiz/use-quiz-session.test.ts (1)
46-49: Consider addingafterEachwithvi.restoreAllMocks()for consistency.The sibling test file
use-quiz-guards.test.tsincludes anafterEachhook withvi.restoreAllMocks(). Adding the same here ensures mock cleanup consistency across test files and prevents potential test pollution.Suggested improvement
beforeEach(() => { sessionStorage.clear(); vi.clearAllMocks(); }); + afterEach(() => { + vi.restoreAllMocks(); + }); it('restores session on reload', async () => {frontend/coverage-quiz/lib/quiz/quiz-crypto.ts.html (1)
1-331: Remove coverage reports from source control and add to.gitignore.The
frontend/coverage-quiz/directory containing auto-generated Istanbul coverage HTML reports is currently tracked in git. These artifacts should not be committed as they:
- Are auto-generated and can be recreated from source
- Bloat the repository with 22+ static files
- Create unnecessary noise in diffs
The current
.gitignorehas/coverageat root level, but this does not excludefrontend/coverage-quiz/. Addfrontend/coverage-quiz/to.gitignoreto prevent future commits of coverage reports.
| function toggleClass(index) { | ||
| missingCoverageElements | ||
| .item(currentIndex) | ||
| .classList.remove('highlighted'); | ||
| missingCoverageElements.item(index).classList.add('highlighted'); | ||
| } |
There was a problem hiding this comment.
Potential null reference on first navigation.
When toggleClass is first called, currentIndex is undefined, so missingCoverageElements.item(currentIndex) returns null, causing a crash on .classList.remove().
🐛 Proposed fix
function toggleClass(index) {
- missingCoverageElements
- .item(currentIndex)
- .classList.remove('highlighted');
+ if (typeof currentIndex === 'number') {
+ missingCoverageElements
+ .item(currentIndex)
+ .classList.remove('highlighted');
+ }
missingCoverageElements.item(index).classList.add('highlighted');
}📝 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.
| function toggleClass(index) { | |
| missingCoverageElements | |
| .item(currentIndex) | |
| .classList.remove('highlighted'); | |
| missingCoverageElements.item(index).classList.add('highlighted'); | |
| } | |
| function toggleClass(index) { | |
| if (typeof currentIndex === 'number') { | |
| missingCoverageElements | |
| .item(currentIndex) | |
| .classList.remove('highlighted'); | |
| } | |
| missingCoverageElements.item(index).classList.add('highlighted'); | |
| } |
🤖 Prompt for AI Agents
In `@frontend/coverage-quiz/block-navigation.js` around lines 24 - 29, toggleClass
currently calls missingCoverageElements.item(currentIndex).classList.remove(...)
but currentIndex can be undefined on first navigation, causing a null reference;
update toggleClass (and/or initialization of currentIndex) to guard the removal
by checking that missingCoverageElements.item(currentIndex) is non-null before
calling .classList.remove, then perform the .classList.add on
missingCoverageElements.item(index) and set currentIndex = index; alternatively
ensure currentIndex is initialized to a valid integer before toggleClass is ever
invoked. Use the function name toggleClass and the variables currentIndex and
missingCoverageElements.item(...) to locate and apply the guard.
| function goToPrevious() { | ||
| var nextIndex = 0; | ||
| if (typeof currentIndex !== 'number' || currentIndex === 0) { | ||
| nextIndex = missingCoverageElements.length - 1; | ||
| } else if (missingCoverageElements.length > 1) { | ||
| nextIndex = currentIndex - 1; | ||
| } | ||
|
|
||
| makeCurrent(nextIndex); | ||
| } | ||
|
|
||
| function goToNext() { | ||
| var nextIndex = 0; | ||
|
|
||
| if ( | ||
| typeof currentIndex === 'number' && | ||
| currentIndex < missingCoverageElements.length - 1 | ||
| ) { | ||
| nextIndex = currentIndex + 1; | ||
| } | ||
|
|
||
| makeCurrent(nextIndex); | ||
| } |
There was a problem hiding this comment.
Missing bounds check for empty element list.
If missingCoverageElements is empty (no uncovered blocks), both goToPrevious and goToNext will call makeCurrent(0), which then calls missingCoverageElements.item(0) returning null and causing a crash.
🐛 Proposed fix - add early return
function goToPrevious() {
+ if (missingCoverageElements.length === 0) {
+ return;
+ }
var nextIndex = 0;
// ...
}
function goToNext() {
+ if (missingCoverageElements.length === 0) {
+ return;
+ }
var nextIndex = 0;
// ...
}🤖 Prompt for AI Agents
In `@frontend/coverage-quiz/block-navigation.js` around lines 41 - 63, Both
navigation functions (goToPrevious and goToNext) call makeCurrent(0) when
missingCoverageElements is empty, which leads to makeCurrent attempting to
access missingCoverageElements.item(0) and crashing; fix by adding an early
guard in each function (or a shared check before navigation) that returns
immediately if missingCoverageElements.length === 0 so makeCurrent is never
called on an empty list, leaving existing index logic unchanged.
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs * (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations * feat(i18n): localize quiz anti-cheat, header and blog filters (#175) * feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes * Update leaderboard-style * Update leaderboard-style * teat(Blog): fix of hover on author, fix of the line * (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes * (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics * fix: npm installing * (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves) * fix:Update leaderboard: fixed background * fix: remove email from CurrentUser type to prevent PII exposure * refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow) * (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout - Fixed mobile tabs in FeaturesSection (icon-only on mobile) - Fixed game bugs: collision detection, animation, scoring system - Added multiple obstacle types with level progression - Improved game sizing for mobile while preserving desktop - Updated TopicsSection with local SVG icons and hover borders - Made DynamicGridBackground static grid opt-in via showStaticGrid prop - Limited SponsorsWall to display max 10 sponsors - Optimized CommunitySection button layout for mobile * refactor: update accent color hover effects to Footer - Update Footer links to use --accent-primary on hover - Update ThemeToggle icons to use --accent-primary on hover - Both components adapt colors to light/dark theme * refactor: improve accessibility - Add focus-visible styles for keyboard navigation accessibility * (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186) * fix:leaderboard update leaderboard-style (#187) * fix:leaderboard update leaderboard-style on mobile (#188) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts --------- Co-authored-by: Viktor Svertoka <victor.svertoka@gmail.com> * (SP: 1) [Frontend] Changing hero headline on shop main page (#190) * (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url * (SP: 1) [Shop] Fix locale cart page and orderid page * (SP: 1) [Frontend] Changin hero headline on shop main page * (SP: 1) [Frontend] Fix styles shop home page, buttons (#191) * Feature/leaderboard style update (#192) * (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195) * Sanity (#196) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * (SP: 3) [AI] Add AI word helper with Groq integration (#200) * (SP: 3) [AI] Add AI word helper with Groq integration - Implement Groq API with Llama 3.1 70B model - Add text selection detection on Q&A page - Create floating "Explain" button - Build draggable modal with 3-language support (uk/en/pl) - Add localStorage caching for instant repeated lookups - Implement guest CTA (login/signup) - Add rate limiting (10 requests/min) - Auth-gated feature (registered users only) Components: - SelectableText: Detects text selection - FloatingExplainButton: Appears on selection - AIWordHelper: Main modal with explanations * (SP: 1) i18n: fix Polish locale and set EN as default * Sanity (#202) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * Sanity (#203) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * (SP: 3) [Frontend] Refactor Header UI and navigation states (#201) * (SP: 3) [Frontend] Refactor Header UI and navigation states - Add icon to the language switcher - Add GitHub icon with stars indicator (frontend only) - Update logo styles - Improve touch interaction styles - Verify correct placement and alignment of all header components - Make mobile header modal full-screen - Disable background scroll when mobile menu is open - Highlight active navigation item - Update navigation styles: - Highlight Shop link when user is on Home pages - Highlight Home link when user is on Shop pages - Style changes only, no routing or logic changes * fix CodeRabbit * update HeaderButton styles * fix: add accessibility for HeaderButton * (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204) * feat(quiz-ui): quiz UI polish - tabs, category accents, color scheme (issues #181, #193, #194) - Refactor QaTabButton to shared CategoryTabButton component - Add category accent colors to QuizCard, buttons, progress indicators - Standardize colors with CSS variables, traffic light timer - Add DynamicGridBackground to quizzes list page - Border-only answer feedback, semi-transparent progress styles * docs: update .gitignore * fix(quiz): align disqualification threshold with warning banner Changed violationsCount > 3 to >= 3 in QuizResult points block to match the warning banner threshold at line 124. * feat(quiz-testing): add quiz unit tests - Configure Vitest for quiz module - Add test factories and setup utilities - Add quiz-crypto tests (13 tests) - Add quiz-session tests (12 tests) * test(quiz): add integration tests for verify-answer API and useAntiCheat hook (#199) - verify-answer.test.ts: 8 tests for API endpoint - Correct/wrong answer verification - Validation errors (missing fields, tampered data) - Security: rejects modified encrypted answers - quiz-anticheat.test.ts: 10 tests for useAntiCheat hook - Detects copy, paste, context-menu, tab-switch events - Respects isActive flag - Reset and cleanup functionality Total quiz tests: 52 (9 setup + 25 unit + 18 integration) * test(quiz): expand test coverage to 90%+ with hooks, API routes, and UI flow Add 28 new tests covering: - useQuizSession hook (6 tests) - useQuizGuards hook (8 tests) - guest-quiz storage (5 tests) - guest-result API route (5 tests) - quiz-slug API route (3 tests) - QuizContainer UI flow (1 test) Coverage: 35% -> 90.94% (quiz scope) Tests: 52 -> 80 * chore: remove coverage-quiz from git, add to .gitignore * chore: add coverage-quiz to .gitignore, fix quiz guards test * Feature/leaderboard style update (#206) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts * fix: move row border to first cell to resolve CodeRabbit issue * fix: move row border to first cell to resolve CodeRabbit issue new * fix(leaderboard): improve table mobile * fix(leaderboard): correct malformed shadow class syntax for avatar glow * test(q&a): add comprehensive qa tests and coverage setup (#208) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * (SP: 1) [Frontend] Remove Contacts References (#211) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * chore(nav): remove contacts page references * Sanity (#209) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * chore(release): update changelog for v0.5.0 * chore(release): v0.5.0 --------- Co-authored-by: liudmylasovetovs <milkaegik@gmail.com> Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com> Co-authored-by: Anna <komrakova.anna@gmail.com> Co-authored-by: AlinaRyabova <alinavr7@gmail.com> Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com> Co-authored-by: YNazymko12 <yulychka12@gmail.com> Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com> Co-authored-by: AlinaRyabova <115992255+AlinaRyabova@users.noreply.github.com> Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com> Co-authored-by: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com>
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs * (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations * feat(i18n): localize quiz anti-cheat, header and blog filters (#175) * feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes * Update leaderboard-style * Update leaderboard-style * teat(Blog): fix of hover on author, fix of the line * (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes * (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics * fix: npm installing * (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves) * fix:Update leaderboard: fixed background * fix: remove email from CurrentUser type to prevent PII exposure * refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow) * (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout - Fixed mobile tabs in FeaturesSection (icon-only on mobile) - Fixed game bugs: collision detection, animation, scoring system - Added multiple obstacle types with level progression - Improved game sizing for mobile while preserving desktop - Updated TopicsSection with local SVG icons and hover borders - Made DynamicGridBackground static grid opt-in via showStaticGrid prop - Limited SponsorsWall to display max 10 sponsors - Optimized CommunitySection button layout for mobile * refactor: update accent color hover effects to Footer - Update Footer links to use --accent-primary on hover - Update ThemeToggle icons to use --accent-primary on hover - Both components adapt colors to light/dark theme * refactor: improve accessibility - Add focus-visible styles for keyboard navigation accessibility * (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style (#187) * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts * fix:leaderboard update leaderboard-style on mobile (#188) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts --------- Co-authored-by: Viktor Svertoka <victor.svertoka@gmail.com> * (SP: 1) [Frontend] Changing hero headline on shop main page (#190) * (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url * (SP: 1) [Shop] Fix locale cart page and orderid page * (SP: 1) [Frontend] Changin hero headline on shop main page * (SP: 1) [Frontend] Fix styles shop home page, buttons (#191) * fix: move row border to first cell to resolve CodeRabbit issue * fix: move row border to first cell to resolve CodeRabbit issue new * Feature/leaderboard style update (#192) * (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195) * Sanity (#196) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * (SP: 3) [AI] Add AI word helper with Groq integration (#200) * (SP: 3) [AI] Add AI word helper with Groq integration - Implement Groq API with Llama 3.1 70B model - Add text selection detection on Q&A page - Create floating "Explain" button - Build draggable modal with 3-language support (uk/en/pl) - Add localStorage caching for instant repeated lookups - Implement guest CTA (login/signup) - Add rate limiting (10 requests/min) - Auth-gated feature (registered users only) Components: - SelectableText: Detects text selection - FloatingExplainButton: Appears on selection - AIWordHelper: Main modal with explanations * (SP: 1) i18n: fix Polish locale and set EN as default * Sanity (#202) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * Sanity (#203) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * (SP: 3) [Frontend] Refactor Header UI and navigation states (#201) * (SP: 3) [Frontend] Refactor Header UI and navigation states - Add icon to the language switcher - Add GitHub icon with stars indicator (frontend only) - Update logo styles - Improve touch interaction styles - Verify correct placement and alignment of all header components - Make mobile header modal full-screen - Disable background scroll when mobile menu is open - Highlight active navigation item - Update navigation styles: - Highlight Shop link when user is on Home pages - Highlight Home link when user is on Shop pages - Style changes only, no routing or logic changes * fix CodeRabbit * update HeaderButton styles * fix: add accessibility for HeaderButton * (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204) * feat(quiz-ui): quiz UI polish - tabs, category accents, color scheme (issues #181, #193, #194) - Refactor QaTabButton to shared CategoryTabButton component - Add category accent colors to QuizCard, buttons, progress indicators - Standardize colors with CSS variables, traffic light timer - Add DynamicGridBackground to quizzes list page - Border-only answer feedback, semi-transparent progress styles * docs: update .gitignore * fix(quiz): align disqualification threshold with warning banner Changed violationsCount > 3 to >= 3 in QuizResult points block to match the warning banner threshold at line 124. * feat(quiz-testing): add quiz unit tests - Configure Vitest for quiz module - Add test factories and setup utilities - Add quiz-crypto tests (13 tests) - Add quiz-session tests (12 tests) * test(quiz): add integration tests for verify-answer API and useAntiCheat hook (#199) - verify-answer.test.ts: 8 tests for API endpoint - Correct/wrong answer verification - Validation errors (missing fields, tampered data) - Security: rejects modified encrypted answers - quiz-anticheat.test.ts: 10 tests for useAntiCheat hook - Detects copy, paste, context-menu, tab-switch events - Respects isActive flag - Reset and cleanup functionality Total quiz tests: 52 (9 setup + 25 unit + 18 integration) * test(quiz): expand test coverage to 90%+ with hooks, API routes, and UI flow Add 28 new tests covering: - useQuizSession hook (6 tests) - useQuizGuards hook (8 tests) - guest-quiz storage (5 tests) - guest-result API route (5 tests) - quiz-slug API route (3 tests) - QuizContainer UI flow (1 test) Coverage: 35% -> 90.94% (quiz scope) Tests: 52 -> 80 * chore: remove coverage-quiz from git, add to .gitignore * chore: add coverage-quiz to .gitignore, fix quiz guards test * fix(leaderboard): improve table mobile * fix(leaderboard): correct malformed shadow class syntax for avatar glow * Feature/leaderboard style update (#206) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts * fix: move row border to first cell to resolve CodeRabbit issue * fix: move row border to first cell to resolve CodeRabbit issue new * fix(leaderboard): improve table mobile * fix(leaderboard): correct malformed shadow class syntax for avatar glow * test(q&a): add comprehensive qa tests and coverage setup (#208) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * (SP: 1) [Frontend] Remove Contacts References (#211) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * chore(nav): remove contacts page references * Sanity (#209) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * chore(release): update changelog for v0.5.0 * chore(release): v0.5.0 * [Refactor] Code Quality Improvements: Accessibility, Mobile Support, … (#213) * fix(leaderboard): adjust podium heights for better visibility on desktop * Feature/leaderboard style update (#214) * fix(leaderboard): fix layout centering * feat(Blog) (#216) * feat(Blog) (#218) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * feat(Blog): added tests * feat(Blog): fix for big post on the post page, added tests * feat(Blog): resolving comments * feat(Blog): fixed hover for social links icins - dark theme * (SP: 1) feat(i18n): translate 404 error page (#217) - Add 404 translations (uk/en/pl) - Implement [Global/Local/Combined] strategy - Add helpful navigation links * (SP: 2) [Frontend] Refactor Home HeroSection and Footer stylestor/home (#221) * (SP:1) fix: 404 page layout (#219) - 404 translations (uk/en/pl) - Implement Global strategy * feat(Blog) (#222) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * feat(Blog): added tests * feat(Blog): fix for big post on the post page, added tests * feat(Blog): resolving comments * feat(Blog): fixed hover for social links icins - dark theme * feat(Blog): bringing the style on the blog page to a single site style * feat(blog): aligning syles * feat(blog): resolving comment from CodeRabbit * feat(blog):fix comment for deployment * Update AI model from 'llama-3.3-70b-versatile' to 'llama3-70b-8192' (#223) * (SP 2) [Frontend] Update Features section content and improve mobile UX (#224) * (SP 2) [Frontend] Update Features section content and improve mobile UX - Features Section: Refined feature content and visuals. - Mobile UX: Improved responsive layout and scaling for feature cards and interactive elements. - Visual Enhancements: Added dynamic particle background effects to the Pricing section. * fix(review): address accessibility, security, and performance feedback * fix(review): resolve accessibility and hydration issues * fix(perf): implement frame-rate independent animations * fix(review): address accessibility, security, and performance feedback * fix(review): enable SSR for features section and support HiDPI canvas * fix(review): correct HiDPI logic for particle canvas measurements * (SP:3) feat(i18n): add UA and PL translations for shop/admin pages Add comprehensive i18n support for shop and admin sections in 3 languages (en, uk, pl). Translation coverage: - Shop pages: main page, products, cart, checkout, orders - Admin pages: dashboard, products management, orders management - Navigation: header, mobile menu, category links - Product components: cards, filters, sort, badges (NEW/SALE) - Category names: Apparel, Lifestyle, Collectibles - All UI buttons, labels, and actions Key changes: - Added ~250+ translation keys to messages/en.json, messages/uk.json, messages/pl.json - Updated 20+ components to use useTranslations() and getTranslations() - Implemented color translation in cart and product detail pages - Translated hero message - Added badge translations * fix(i18n): correct translation keys and localization in shop pages - Replace confusing error.order with success.orderLabel in checkout success page heading - Localize boolean stockRestored display (yes/no instead of true/false) in order details - Fix active state detection for shop category links in mobile menu using search params - Add missing translation keys (orderLabel, yes, no) to all locales (en, uk, pl) * fix(netlify): resolve AI API crash and 404 locale/theme issues AI fixes: - Extract getClientIp to separate file (avoid db import crash) - Add missing zod dependency to package.json 404 page fixes: - Use NEXT_LOCALE cookie for locale detection on Netlify - Add theme detection script in root layout - Update styling with hero background and gradient text * Update frontend/app/not-found.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * (SP:3) feat(i18n): translate about page and auth form validation messages - Add about page translations (EN, UK, PL) - Add auth.fields.validation translations for form errors * fix(api): resolve Netlify 503 errors and harden AI explain endpoint - Use dynamic import for groq-sdk (Netlify compatibility) - Bypass rate limiting for unknown IPs (serverless safety) - Safe JSON parsing with request.text() + empty body check - Fix ReferenceError: remove undefined errorMessage variable - Remove sensitive debug info from client responses - Add i18n keys: pricing.heading, sponsors.ctaAriaLabel * feat(api): add GET health check endpoint for ai-explain * chore(release): v0.5.1 --------- Co-authored-by: liudmylasovetovs <milkaegik@gmail.com> Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com> Co-authored-by: Anna <komrakova.anna@gmail.com> Co-authored-by: AlinaRyabova <alinavr7@gmail.com> Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com> Co-authored-by: YNazymko12 <yulychka12@gmail.com> Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com> Co-authored-by: AlinaRyabova <115992255+AlinaRyabova@users.noreply.github.com> Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com> Co-authored-by: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com> Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com> Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* (SP: 1) [Security] Enforce origin posture for shop APIs (admin/checkout same-origin; internal/webhooks non-browser) + docs * (SP: 1) [DB] Align stripe_events.order_id FK CASCADE across schema and migrations * feat(i18n): localize quiz anti-cheat, header and blog filters (#175) * feat(Blog): Adding last published post to the blog and category page, recommended posts, Changing styles to one unified format, Bug fixes * Update leaderboard-style * Update leaderboard-style * teat(Blog): fix of hover on author, fix of the line * (SP: 3) [Observability] Extend structured logging + correlation IDs across all shop routes; purge console.*; enforce explicit error codes * (SP: 1) [Admin][Security] Add safe product delete (PRODUCT_IN_USE) + mobile cards UI; tighten env/docs, locale normalization, cache-control, and logging semantics * fix: npm installing * (SP: 1) [Admin] Align products list in use checks with DB column names (order_items/inventory_moves) * fix:Update leaderboard: fixed background * fix: remove email from CurrentUser type to prevent PII exposure * refactor: align leaderboard UI with brand style (fixed bg, css vars, podium glow) * (SP: 1) [Frontend] About Us Page. Fixed game, topics, mobile layout - Fixed mobile tabs in FeaturesSection (icon-only on mobile) - Fixed game bugs: collision detection, animation, scoring system - Added multiple obstacle types with level progression - Improved game sizing for mobile while preserving desktop - Updated TopicsSection with local SVG icons and hover borders - Made DynamicGridBackground static grid opt-in via showStaticGrid prop - Limited SponsorsWall to display max 10 sponsors - Optimized CommunitySection button layout for mobile * refactor: update accent color hover effects to Footer - Update Footer links to use --accent-primary on hover - Update ThemeToggle icons to use --accent-primary on hover - Both components adapt colors to light/dark theme * refactor: improve accessibility - Add focus-visible styles for keyboard navigation accessibility * (SP: 1) [Shop] Fix Stripe checkout success redirect (remove duplicate locale /uk/uk) (#186) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style (#187) * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts * fix:leaderboard update leaderboard-style on mobile (#188) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts --------- * (SP: 1) [Frontend] Changing hero headline on shop main page (#190) * (SP: 1) [Shop] Fix checkout redirect 404 by removing duplicate locale in in-app routes and Stripe return_url * (SP: 1) [Shop] Fix locale cart page and orderid page * (SP: 1) [Frontend] Changin hero headline on shop main page * (SP: 1) [Frontend] Fix styles shop home page, buttons (#191) * fix: move row border to first cell to resolve CodeRabbit issue * fix: move row border to first cell to resolve CodeRabbit issue new * Feature/leaderboard style update (#192) * (SP: 7) [UI] Quiz UI polish: tabs styling, category accents, color scheme (#181, #193, #194) (#195) * Sanity (#196) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * (SP: 3) [AI] Add AI word helper with Groq integration (#200) * (SP: 3) [AI] Add AI word helper with Groq integration - Implement Groq API with Llama 3.1 70B model - Add text selection detection on Q&A page - Create floating "Explain" button - Build draggable modal with 3-language support (uk/en/pl) - Add localStorage caching for instant repeated lookups - Implement guest CTA (login/signup) - Add rate limiting (10 requests/min) - Auth-gated feature (registered users only) Components: - SelectableText: Detects text selection - FloatingExplainButton: Appears on selection - AIWordHelper: Main modal with explanations * (SP: 1) i18n: fix Polish locale and set EN as default * Sanity (#202) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * Sanity (#203) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * (SP: 3) [Frontend] Refactor Header UI and navigation states (#201) * (SP: 3) [Frontend] Refactor Header UI and navigation states - Add icon to the language switcher - Add GitHub icon with stars indicator (frontend only) - Update logo styles - Improve touch interaction styles - Verify correct placement and alignment of all header components - Make mobile header modal full-screen - Disable background scroll when mobile menu is open - Highlight active navigation item - Update navigation styles: - Highlight Shop link when user is on Home pages - Highlight Home link when user is on Shop pages - Style changes only, no routing or logic changes * fix CodeRabbit * update HeaderButton styles * fix: add accessibility for HeaderButton * (SP: 3) [Testing] Vitest config + unit + integration tests for quiz module (#204) * feat(quiz-ui): quiz UI polish - tabs, category accents, color scheme (issues #181, #193, #194) - Refactor QaTabButton to shared CategoryTabButton component - Add category accent colors to QuizCard, buttons, progress indicators - Standardize colors with CSS variables, traffic light timer - Add DynamicGridBackground to quizzes list page - Border-only answer feedback, semi-transparent progress styles * docs: update .gitignore * fix(quiz): align disqualification threshold with warning banner Changed violationsCount > 3 to >= 3 in QuizResult points block to match the warning banner threshold at line 124. * feat(quiz-testing): add quiz unit tests - Configure Vitest for quiz module - Add test factories and setup utilities - Add quiz-crypto tests (13 tests) - Add quiz-session tests (12 tests) * test(quiz): add integration tests for verify-answer API and useAntiCheat hook (#199) - verify-answer.test.ts: 8 tests for API endpoint - Correct/wrong answer verification - Validation errors (missing fields, tampered data) - Security: rejects modified encrypted answers - quiz-anticheat.test.ts: 10 tests for useAntiCheat hook - Detects copy, paste, context-menu, tab-switch events - Respects isActive flag - Reset and cleanup functionality Total quiz tests: 52 (9 setup + 25 unit + 18 integration) * test(quiz): expand test coverage to 90%+ with hooks, API routes, and UI flow Add 28 new tests covering: - useQuizSession hook (6 tests) - useQuizGuards hook (8 tests) - guest-quiz storage (5 tests) - guest-result API route (5 tests) - quiz-slug API route (3 tests) - QuizContainer UI flow (1 test) Coverage: 35% -> 90.94% (quiz scope) Tests: 52 -> 80 * chore: remove coverage-quiz from git, add to .gitignore * chore: add coverage-quiz to .gitignore, fix quiz guards test * fix(leaderboard): improve table mobile * fix(leaderboard): correct malformed shadow class syntax for avatar glow * Feature/leaderboard style update (#206) * fix:leaderboard update leaderboard-style * fix:leaderboard update leaderboard-style on mobile * fix: resolve CodeRabbit issues and conflicts * fix: move row border to first cell to resolve CodeRabbit issue * fix: move row border to first cell to resolve CodeRabbit issue new * fix(leaderboard): improve table mobile * fix(leaderboard): correct malformed shadow class syntax for avatar glow * test(q&a): add comprehensive qa tests and coverage setup (#208) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * (SP: 1) [Frontend] Remove Contacts References (#211) * test(q&a): add comprehensive qa tests and coverage setup * test(q&a): align mocks and reset in qa tests * chore(nav): remove contacts page references * Sanity (#209) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * chore(release): update changelog for v0.5.0 * chore(release): v0.5.0 * [Refactor] Code Quality Improvements: Accessibility, Mobile Support, … (#213) * fix(leaderboard): adjust podium heights for better visibility on desktop * Feature/leaderboard style update (#214) * fix(leaderboard): fix layout centering * feat(Blog) (#216) * feat(Blog) (#218) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * feat(Blog): added tests * feat(Blog): fix for big post on the post page, added tests * feat(Blog): resolving comments * feat(Blog): fixed hover for social links icins - dark theme * (SP: 1) feat(i18n): translate 404 error page (#217) - Add 404 translations (uk/en/pl) - Implement [Global/Local/Combined] strategy - Add helpful navigation links * (SP: 2) [Frontend] Refactor Home HeroSection and Footer stylestor/home (#221) * (SP:1) fix: 404 page layout (#219) - 404 translations (uk/en/pl) - Implement Global strategy * feat(Blog) (#222) * feat(Blog):fix for clickable link in post details, fix for author details * feat(Blog):refactoring after removing author modal * feat(Blog): fix unified date format * feat(Blog): Fix for click-outside-to-close search, recommended posts are limited to 3 * feat(Blog): selectedAuthorData fixed * feat(Blog): Added description for /blog/[slug] metadata, Added Schema.org JSON‑LD for Article (BlogPosting) and BreadcrumbList , Added <time datetime> tags where blog dates renders * feat(Blog): fix hover social links, fixed duplication not found search * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added: breadcrumbs to the post details page and updated the BreadcrumbList, logo to the cocial links in User info, Fixed: main container alignment, category navigation in breadcrumbs * feat(Blog): Added scroll on the main blog page on filtering by author, fied breadcrumbs category translaion, added category to the recommended cards, fixed search for localisations * feat(Blog): Changed image size on the post details page * feat(Blog): added tests * feat(Blog): fix for big post on the post page, added tests * feat(Blog): resolving comments * feat(Blog): fixed hover for social links icins - dark theme * feat(Blog): bringing the style on the blog page to a single site style * feat(blog): aligning syles * feat(blog): resolving comment from CodeRabbit * feat(blog):fix comment for deployment * Update AI model from 'llama-3.3-70b-versatile' to 'llama3-70b-8192' (#223) * (SP 2) [Frontend] Update Features section content and improve mobile UX (#224) * (SP 2) [Frontend] Update Features section content and improve mobile UX - Features Section: Refined feature content and visuals. - Mobile UX: Improved responsive layout and scaling for feature cards and interactive elements. - Visual Enhancements: Added dynamic particle background effects to the Pricing section. * fix(review): address accessibility, security, and performance feedback * fix(review): resolve accessibility and hydration issues * fix(perf): implement frame-rate independent animations * fix(review): address accessibility, security, and performance feedback * fix(review): enable SSR for features section and support HiDPI canvas * fix(review): correct HiDPI logic for particle canvas measurements * (SP:3) feat(i18n): add UA and PL translations for shop/admin pages Add comprehensive i18n support for shop and admin sections in 3 languages (en, uk, pl). Translation coverage: - Shop pages: main page, products, cart, checkout, orders - Admin pages: dashboard, products management, orders management - Navigation: header, mobile menu, category links - Product components: cards, filters, sort, badges (NEW/SALE) - Category names: Apparel, Lifestyle, Collectibles - All UI buttons, labels, and actions Key changes: - Added ~250+ translation keys to messages/en.json, messages/uk.json, messages/pl.json - Updated 20+ components to use useTranslations() and getTranslations() - Implemented color translation in cart and product detail pages - Translated hero message - Added badge translations * fix(i18n): correct translation keys and localization in shop pages - Replace confusing error.order with success.orderLabel in checkout success page heading - Localize boolean stockRestored display (yes/no instead of true/false) in order details - Fix active state detection for shop category links in mobile menu using search params - Add missing translation keys (orderLabel, yes, no) to all locales (en, uk, pl) * fix(netlify): resolve AI API crash and 404 locale/theme issues AI fixes: - Extract getClientIp to separate file (avoid db import crash) - Add missing zod dependency to package.json 404 page fixes: - Use NEXT_LOCALE cookie for locale detection on Netlify - Add theme detection script in root layout - Update styling with hero background and gradient text * Update frontend/app/not-found.tsx * (SP:3) feat(i18n): translate about page and auth form validation messages - Add about page translations (EN, UK, PL) - Add auth.fields.validation translations for form errors * fix(api): resolve Netlify 503 errors and harden AI explain endpoint - Use dynamic import for groq-sdk (Netlify compatibility) - Bypass rate limiting for unknown IPs (serverless safety) - Safe JSON parsing with request.text() + empty body check - Fix ReferenceError: remove undefined errorMessage variable - Remove sensitive debug info from client responses - Add i18n keys: pricing.heading, sponsors.ctaAriaLabel * feat(api): add GET health check endpoint for ai-explain * chore(release): v0.5.1 --------- Co-authored-by: liudmylasovetovs <milkaegik@gmail.com> Co-authored-by: Tetiana Zorii <131365289+TiZorii@users.noreply.github.com> Co-authored-by: Anna <komrakova.anna@gmail.com> Co-authored-by: AlinaRyabova <alinavr7@gmail.com> Co-authored-by: Yevhenii Datsenko <yevheniydatsenko@gmail.com> Co-authored-by: YNazymko12 <yulychka12@gmail.com> Co-authored-by: liudmylasovetovs <127711697+liudmylasovetovs@users.noreply.github.com> Co-authored-by: AlinaRyabova <115992255+AlinaRyabova@users.noreply.github.com> Co-authored-by: Lesia Soloviova <106915140+LesiaUKR@users.noreply.github.com> Co-authored-by: Yuliia Nazymko <122815071+YNazymko12@users.noreply.github.com> Co-authored-by: Yevhenii Datsenko <134847096+yevheniidatsenko@users.noreply.github.com> Co-authored-by: tetiana zorii <tanyusha.zoriy@gmail.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Week 6
Closes #197
Closes #198
Closes #199
Closes #205
Goal
Set up quiz testing foundation and achieve 90%+ coverage for critical quiz logic, hooks, API routes, and UI flow.
Scope
Changes
Setup / Infrastructure
lib/tests/__mocks__/server-only.ts(server-only mock)lib/tests/factories/quiz/quiz.tslib/tests/quiz/setup.tslib/tests/quiz/quiz-setup.test.ts(9 tests)Unit Tests
lib/tests/quiz/quiz-crypto.test.ts(13 tests)lib/tests/quiz/quiz-session.test.ts(12 tests)lib/tests/quiz/use-quiz-session.test.ts(6 tests)lib/tests/quiz/guest-quiz.test.ts(5 tests)Integration Tests
lib/tests/quiz/verify-answer.test.ts(8 tests)lib/tests/quiz/quiz-anticheat.test.ts(10 tests)lib/tests/quiz/use-quiz-guards.test.ts(8 tests)lib/tests/quiz/guest-result-route.test.ts(5 tests)lib/tests/quiz/quiz-slug-route.test.ts(3 tests)components/quiz/tests/quiz-container-flow.test.tsx(1 test)Test Metrics
Coverage by Module
Expected Impact
Out of Scope
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.