Skip to content

Conversation

@Creeland
Copy link
Contributor

@Creeland Creeland commented Dec 16, 2025

Summary

  • Add unit tests asserting legacy slugs never trigger LIKE matching in Course Builder DB lookups.
  • Add integration tests for loadLesson and loadResourcesForCourse to ensure legacy lesson/course titles and ordering are not polluted by unrelated Course Builder records.

Test plan

  • pnpm test:ci -- src/lib/__tests__/get-course-builder-metadata.test.ts
  • pnpm test:ci -- src/lib/__tests__/load-lesson.integration.test.ts src/lib/__tests__/course-resources.integration.test.ts

Summary by CodeRabbit

  • Bug Fixes

    • Improved legacy lesson fetching to fail gracefully on fetch or parse errors (no uncaught exceptions).
  • Performance

    • Increased GraphQL playlist page size for faster batch loading.
  • Tests

    • Added integration tests covering course resources, lesson loading, and course-builder metadata behaviors (ensuring correct ordering, titles, and query handling).

…guide-to-react-broken-lesson-titles]

Add tests to ensure Course Builder DB queries only use LIKE matching when a
slug contains a "~<id>" suffix, preventing legacy slugs from accidentally
matching and overwriting titles.
…rs-guide-to-react-broken-lesson-titles]

Covers the full loadLesson and loadResourcesForCourse flows with mocked
GraphQL, Sanity, and Course Builder DB. Ensures legacy slugs never trigger
LIKE-based Course Builder matching and titles cannot be overwritten by
unrelated records.
@vercel
Copy link

vercel bot commented Dec 16, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
egghead-io-nextjs Ready Ready Preview, Comment Feb 7, 2026 11:24pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 16, 2025

📝 Walkthrough

Walkthrough

Adds integration tests that verify legacy slug handling avoids LIKE-based DB queries for lessons and courses; increases playlist GraphQL page size from 25 to 200; and makes legacy-lesson fetch in [post].tsx resilient to non-OK responses and exceptions.

Changes

Cohort / File(s) Summary
Legacy slug & course/lesson integration tests
src/lib/__tests__/course-resources.integration.test.ts, src/lib/__tests__/load-lesson.integration.test.ts, src/lib/__tests__/get-course-builder-metadata.test.ts
New integration tests covering legacy vs course-builder slug paths. Mocks mysql2/promise pool/connection, GraphQL and Sanity clients, and asserts SQL parameter usage (exact-match vs LIKE), pool release, and returned lesson/course fields.
GraphQL pagination
src/lib/playlists.ts
Increased per_page in loadAllPlaylistsByPage GraphQL pagination call from 25 to 200.
Legacy lesson fetch resilience
src/pages/[post].tsx
Replaced direct fetch+json with guarded try/catch; checks response.ok before parsing, logs warnings for non-OK responses, and catches exceptions to avoid throwing on fetch/parse failures.

Sequence Diagram(s)

(Skipped — changes are tests, a pagination constant tweak, and UI fetch error handling; no new multi-component control flow requiring sequence diagrams.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐇 I dug through slugs both new and old,
Exact matches found — no LIKE to hold.
I fetch with care, I page by more,
Two hundred beats twenty-five — hooray, encore! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective of the PR: adding test coverage for Course Builder slug gating to prevent LIKE-based matching issues with legacy slugs.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cp/beginners-guide-to-react-broken-lesson-titles

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…for courses to 3600 seconds

Updated the loadAllPlaylistsByPage function to fetch 200 playlists per request instead of 25. Additionally, modified the getStaticProps function in the courses index to revalidate every hour, improving data freshness.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/pages/courses/index.tsx (1)

16-18: ISR implementation looks good, but appears unrelated to PR objectives.

Adding revalidate: 3600 enables hourly Incremental Static Regeneration, which is appropriate for a courses index that doesn't require real-time updates. The implementation is correct.

However, this optimization appears unrelated to the PR's stated objectives (adding unit and integration test coverage for Course Builder slug gating). If this change was discovered as a necessary improvement during testing, consider documenting the connection in the PR description.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6f6569 and 3a00389.

📒 Files selected for processing (2)
  • src/lib/playlists.ts (1 hunks)
  • src/pages/courses/index.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,mjs,cjs,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging-session.mdc)

**/*.{js,mjs,cjs,ts,tsx}: On application startup, generate a timestamp YYYY-MM-DD-HH-MM-SS and create logs/.log; append all log output to this file
Each application run must create a new log file, preserving previous logs
Use a logger (e.g., pino or winston) or file writes to implement logging
Record start/end of major operations, successful paths, handled errors, and unexpected failures
Include environment info (e.g., CLI arguments and Node version) in logs
Provide a toggle to disable file logging: LOG_LEVEL=off or --no-log; when disabled, do not create the log file and suppress log output
Prefer structured log lines (JSON or clearly delimited) with level, timestamp, and message in each entry
Logs must capture both happy paths and errors while maintaining readability and sufficient detail for troubleshooting

Files:

  • src/lib/playlists.ts
  • src/pages/courses/index.tsx
{src,app,lib,packages}/**

📄 CodeRabbit inference engine (.cursor/rules/project-update-user-rules.mdc)

Examine main source directories (e.g., src/, app/, lib/, packages/) to understand module organization and architectural patterns

Files:

  • src/lib/playlists.ts
  • src/pages/courses/index.tsx
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use the @/ path alias for imports from the src directory

Files:

  • src/lib/playlists.ts
  • src/pages/courses/index.tsx
src/lib/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Place database queries and data-fetching logic in src/lib/[feature] and mark server-only files with 'use server'

Files:

  • src/lib/playlists.ts
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/react-rules.mdc)

**/*.{tsx,jsx}: Do not include non-memoized functions in React useEffect dependency arrays to avoid infinite re-renders
For effects that should only run on mount/unmount, use an empty dependency array [] in useEffect
If a function must be a dependency in useEffect, memoize it with useCallback so its identity is stable

Files:

  • src/pages/courses/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.tsx: Prefer Tailwind utility classes for styling in components; use CSS Modules only for complex styles
Use trpc.useQuery() for client-side data fetching

Files:

  • src/pages/courses/index.tsx
src/pages/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

In legacy pages, keep files focused on orchestration/layout and import extracted modules during migration

Files:

  • src/pages/courses/index.tsx
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: skillrecordings/egghead-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-02T17:59:16.787Z
Learning: Applies to src/lib/**/*course-builder*.ts : Use flexible slug matching in SQL: id = ? OR JSON_UNQUOTE(JSON_EXTRACT(fields, '$.slug')) = ?
Learnt from: CR
Repo: skillrecordings/egghead-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-09-02T17:59:16.787Z
Learning: Applies to src/lib/**/*course-builder*.ts : Identify content types as specified (courses: type='post' with fields.postType='course'; videos: type='videoResource') and model relationships via egghead_ContentResourceResource
🔇 Additional comments (1)
src/lib/playlists.ts (1)

53-53: Document GraphQL endpoint pagination limits or justify the 200-item page size choice.

This change was intentional per the commit history, but the per_page value of 200 lacks inline documentation or endpoint specifications. While the retry logic (5 attempts) indicates the change works in practice, without egghead's GraphQL API documentation, the endpoint's actual capacity limits cannot be verified. Consider: (1) Adding a code comment explaining why 200 was chosen, (2) Documenting the endpoint's pagination limits in a config or README, or (3) Moving this optimization to a separate PR/issue if it's orthogonal to the slug gating feature.

Eliminated the revalidation parameter from the getStaticProps function in the courses index, simplifying the data fetching logic.
} = await request(config.graphQLEndpoint, query, {
page: currentPage,
per_page: 25,
per_page: 200,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

loadAllPlaylistsByPage fetches 25 items per page sequentially. This causes many slow network roundtrips.

Copy link
Contributor

Choose a reason for hiding this comment

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

this is probably too much data and will be slower, this has worked for literally years so that's interesting to me that it'd be an issue now

Enhanced the getStaticProps function to include error handling when fetching legacy lesson data, ensuring better resilience and logging of fetch failures.
@joelhooks joelhooks merged commit cd9f16c into main Feb 7, 2026
6 checks passed
@joelhooks joelhooks deleted the cp/beginners-guide-to-react-broken-lesson-titles branch February 7, 2026 23:35
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.

2 participants