From 3d4cda76644b5aef8dd431cbc59c8934bbf77f60 Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:42:10 +0100 Subject: [PATCH 1/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../11.test-db/01.problem.setup/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From 5b860e7270435e121e5363d9d2a5fe03c837558a Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:43:55 +0100 Subject: [PATCH 2/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../11.test-db/01.solution.setup/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From cb25cc849d20ba47db41122c47e86aa0e85d0251 Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:45:27 +0100 Subject: [PATCH 3/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../02.problem.isolated-db/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts b/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From f221d68e5fe66700a8815e106b718aebbdfeae4d Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:46:26 +0100 Subject: [PATCH 4/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../02.solution.isolated-db/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts b/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From 91ff7055c4461a1364509b51d0b80d4be2072f37 Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:47:36 +0100 Subject: [PATCH 5/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../03.problem.global-setup/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From 24f30cbb8ba8e54b6d5a07adc28830fdb025be38 Mon Sep 17 00:00:00 2001 From: Chidiebere Ekennia <54110155+Davien21@users.noreply.github.com> Date: Sun, 25 Oct 2026 04:48:28 +0100 Subject: [PATCH 6/9] fix: correct toHaveRedirect failure message in 11.test-db --- .../03.solution.global-setup/tests/setup/custom-matchers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts index 2fc576bef..bfacd84e4 100644 --- a/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts @@ -23,7 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ - location ? 'no redirect' : this.utils.printReceived(location) + location ? this.utils.printReceived(location) : 'no redirect' }`, } } From 66ce2b486492c3b271fad3e542b00ad8b23664b9 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 25 Oct 2026 04:31:58 +0000 Subject: [PATCH 7/9] fix: green CI for fork PRs and note corrected redirect matcher Checkout the PR head and run epicshop setup so Setup works for forks instead of cloning epicweb-dev and missing fork-only branches. Pin the Test job to ubuntu-24.04 because Playwright 1.56.1 does not support ubuntu26.04. Add a short learner note next to the corrected toHaveRedirect failure message ternary. Supersedes the follow-up needed on #46 (maintainer could not push to the fork). Keeps Davien21's matcher fix commits. Co-authored-by: Kent C. Dodds --- .github/workflows/validate.yml | 22 ++++++++++++++----- .../tests/setup/custom-matchers.ts | 1 + .../tests/setup/custom-matchers.ts | 1 + .../tests/setup/custom-matchers.ts | 1 + .../tests/setup/custom-matchers.ts | 1 + .../tests/setup/custom-matchers.ts | 1 + .../tests/setup/custom-matchers.ts | 1 + 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index f04f5aafb..a491d8e29 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -21,6 +21,13 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] runs-on: ${{ matrix.os }} steps: + # Checkout the PR head (works for forks) instead of epicshop add + # repo#branch, which only clones epicweb-dev and cannot see fork branches. + - name: ⬇️ Checkout repo + uses: actions/checkout@v4 + with: + path: workshop + - name: ⎔ Setup node uses: actions/setup-node@v4 with: @@ -30,8 +37,9 @@ jobs: # intentionally fail solution tests/types, which would create false CI red. # Use bash explicitly: Windows runners default to PowerShell, which cannot # parse this retry loop. - - name: ▶️ Add repo + - name: ▶️ Setup workshop shell: bash + working-directory: ./workshop env: # Kept getting npm ECOMPROMISED errors on windows. This fixed it. npm_config_cache: ${{ runner.temp }}/npm-cache @@ -43,9 +51,9 @@ jobs: max_attempts=3 delay_seconds=20 while true; do - echo "::group::epicshop add attempt ${attempt}/${max_attempts}" + echo "::group::epicshop setup attempt ${attempt}/${max_attempts}" set +e - npx --yes epicshop@latest add ${{ github.event.repository.name }}#${{ github.head_ref || github.ref_name }} ./workshop + npx --yes epicshop@latest setup status=$? set -e echo "::endgroup::" @@ -53,10 +61,10 @@ jobs: exit 0 fi if [ "$attempt" -ge "$max_attempts" ]; then - echo "epicshop add failed after ${max_attempts} attempts" >&2 + echo "epicshop setup failed after ${max_attempts} attempts" >&2 exit "$status" fi - echo "epicshop add failed (exit ${status}); retrying in ${delay_seconds}s..." + echo "epicshop setup failed (exit ${status}); retrying in ${delay_seconds}s..." sleep "$delay_seconds" delay_seconds=$((delay_seconds * 2)) attempt=$((attempt + 1)) @@ -85,7 +93,9 @@ jobs: name: 🧪 Test # Browser installation plus solution-app tests can exceed the setup budget. timeout-minutes: 30 - runs-on: ubuntu-latest + # Pin 24.04: ubuntu-latest moved to 26.04, and Playwright 1.56.1 in this + # lockfile does not support chromium on ubuntu26.04 yet. + runs-on: ubuntu-24.04 steps: - name: ⬇️ Checkout repo uses: actions/checkout@v4 diff --git a/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/01.problem.setup/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } diff --git a/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/01.solution.setup/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } diff --git a/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts b/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/02.problem.isolated-db/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } diff --git a/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts b/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/02.solution.isolated-db/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } diff --git a/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/03.problem.global-setup/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } diff --git a/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts b/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts index bfacd84e4..625ee3fb9 100644 --- a/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts +++ b/exercises/11.test-db/03.solution.global-setup/tests/setup/custom-matchers.ts @@ -23,6 +23,7 @@ expect.extend({ ? ` to ${this.utils.printExpected(redirectTo)}` : '' } but got ${ + // Note: the videos show these swapped; this is the corrected order so the failure message prints the received location when there is one. location ? this.utils.printReceived(location) : 'no redirect' }`, } From f37e2ee7d667199ee4f098051f02ecfe369cde85 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 25 Oct 2026 05:04:02 +0000 Subject: [PATCH 8/9] fix: skip Playwright install in solution Test CI Solution apps use vitest for npm run test; epicshop/test.js never runs test:e2e. The with-deps Chromium install has been hanging after download on GitHub Actions (cancelled on this PR and on recent main), so drop it. Co-authored-by: Kent C. Dodds --- .github/workflows/validate.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index a491d8e29..f77111e0c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -108,9 +108,9 @@ jobs: - name: 📦 Install dependencies run: npm ci - - name: 🎭 Install Playwright browser - if: ${{ hashFiles('epicshop/test.js') != '' }} - run: npx playwright install --with-deps chromium + # Solution CI runs `npm run test` (vitest) via epicshop/test.js, not + # Playwright e2e (`test:e2e`). Skip browser install: with-deps has been + # hanging after the Chromium download on GHA (also cancelled on main). - name: ◭ Generate Prisma clients if: ${{ hashFiles('epicshop/test.js') != '' }} From 6ef797df221a31dba2c08ef63bd321e4a2a07491 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 25 Oct 2026 05:17:15 +0000 Subject: [PATCH 9/9] fix: restore solution Test CI from #45 after epicshop overwrite Epicshop workflow updates dropped the Node 22 Test runner, setup:custom prep, and the completed-Vitest-only app filter from #45. Without those, solution CI fails on Playwright-collected e2e suites and Node 26 AbortSignal/MSW issues. Restore that Test job shape; keep fork-safe Setup and skip hung Playwright browser install. Co-authored-by: Kent C. Dodds --- .github/workflows/validate.yml | 46 ++++++++++++---------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index f77111e0c..152e1cf5c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -103,45 +103,31 @@ jobs: - name: ⎔ Setup node uses: actions/setup-node@v4 with: - node-version: 26 + # The workshop's pinned MSW/Undici stack has an AbortSignal realm + # incompatibility on Node 26. Node 22 is supported by package.json. + # Restores the Test job config from #45 that epicshop updates overwrote. + node-version: 22 - name: 📦 Install dependencies run: npm ci - # Solution CI runs `npm run test` (vitest) via epicshop/test.js, not - # Playwright e2e (`test:e2e`). Skip browser install: with-deps has been - # hanging after the Chromium download on GHA (also cancelled on main). - - - name: ◭ Generate Prisma clients - if: ${{ hashFiles('epicshop/test.js') != '' }} - run: | - set -euo pipefail - shopt -s globstar nullglob - schemas=() - for schema in ./exercises/**/prisma/schema.prisma; do - app_dir="${schema%/prisma/schema.prisma}" - app_name="${app_dir##*/}" - if [[ "$app_name" =~ ^[0-9]+\.solution(\..+)?$ ]]; then - schemas+=("$schema") - fi - done - if [ "${#schemas[@]}" -eq 0 ]; then - echo "No solution-app Prisma schemas found; skipping Prisma client generation." - exit 0 - fi - for schema in "${schemas[@]}"; do - app_dir="${schema%/prisma/schema.prisma}" - echo "::group::prisma generate in ${app_dir}" - (cd "$app_dir" && npx prisma generate) - echo "::endgroup::" - done + # Solution CI runs vitest via epicshop/test.js, not Playwright e2e. + # Skip browser install: with-deps has been hanging after Chromium download. + - name: 🏗 Prepare solution tests + env: + SKIP_PLAYWRIGHT: true + SKIP_PLAYGROUND: true + run: npm run setup:custom - # Workshops ship epicshop/test.js (not .ts). `..s` runs solution apps only. + # Exercises 1-3 contain Playwright suites, which cannot be collected by + # their `npm test` Vitest command. Run every test in the completed Vitest + # solution for exercises 4-11; intermediate steps can intentionally + # demonstrate failing tests that later steps fix. - name: 🧪 Run solution tests run: | set -euo pipefail if [ -f ./epicshop/test.js ]; then - node ./epicshop/test.js ..s + node ./epicshop/test.js '4.4.s,5.2.s,6.2.s,7.2.s,8.3.s,9.3.s,10.1.s,11.3.s' else echo "No epicshop/test.js in this workshop; skipping solution-app test runner." fi