diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e05eaf17..15f9524e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -53,6 +53,10 @@ jobs: APP_URL: http://0.0.0.0:8008 BLOCK_REMOTE_FONTS: true + - name: Check for unused snapshots + if: steps.tests.outcome == 'success' + run: yarn test:snapshots:check + - name: Authenticate on GCS if: steps.tests.outcome == 'failure' uses: google-github-actions/auth@v2 diff --git a/.github/workflows/update-snapshots.yml b/.github/workflows/update-snapshots.yml index 97e7dd14..80269cb9 100644 --- a/.github/workflows/update-snapshots.yml +++ b/.github/workflows/update-snapshots.yml @@ -32,6 +32,9 @@ jobs: working-directory: apps/react run: yarn test:screenshots:update + - name: Prune unused snapshots + run: yarn test:snapshots:prune + - name: Commit and push updated snapshots env: # expose the PAT for the push @@ -39,7 +42,7 @@ jobs: run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add apps/react/tests/*-snapshots/* || true + git add -A apps/react/tests/*-snapshots || true git commit -m "chore: update Playwright screenshot snapshots" || echo "No changes to commit" BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" echo "Pushing updates to branch: $BRANCH" diff --git a/apps/react/tests/custom-deck-notation-to-study.spec.ts-snapshots/custom-deck-notation-to-study-list.png b/apps/react/tests/custom-deck-notation-to-study.spec.ts-snapshots/custom-deck-notation-to-study-list.png deleted file mode 100644 index ba907dba..00000000 Binary files a/apps/react/tests/custom-deck-notation-to-study.spec.ts-snapshots/custom-deck-notation-to-study-list.png and /dev/null differ diff --git a/package.json b/package.json index 6fb0a4a0..1cc716e4 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "scripts": { "dev": "concurrently \"yarn workspace MemoryFlashServer dev\" \"yarn workspace MemoryFlashReact dev\"", "test": "yarn workspace MemoryFlashServer test && yarn workspace MemoryFlashCore test && yarn workspace MemoryFlashReact test:screenshots", - "test:codex": "yarn workspace MemoryFlashServer build && yarn workspace MemoryFlashReact build && yarn workspace MemoryFlashServer test && yarn workspace MemoryFlashCore test" + "test:codex": "yarn workspace MemoryFlashServer build && yarn workspace MemoryFlashReact build && yarn workspace MemoryFlashServer test && yarn workspace MemoryFlashCore test", + "test:snapshots:check": "node scripts/check-unused-snapshots.js", + "test:snapshots:prune": "node scripts/check-unused-snapshots.js --prune" }, "workspaces": [ "apps/*", diff --git a/scripts/check-unused-snapshots.js b/scripts/check-unused-snapshots.js new file mode 100644 index 00000000..12955ca8 --- /dev/null +++ b/scripts/check-unused-snapshots.js @@ -0,0 +1,43 @@ +const fs = require('fs'); +const path = require('path'); + +function gather(dir) { + const entries = fs.readdirSync(dir, { withFileTypes: true }); + const files = []; + for (const e of entries) { + const full = path.join(dir, e.name); + if (e.isDirectory()) files.push(...gather(full)); + else if (e.isFile() && full.endsWith('.png')) files.push(full); + } + return files; +} + +const root = path.join(__dirname, '..', 'apps', 'react', 'tests'); +const snaps = gather(root).filter((f) => f.includes('-snapshots')); +const unused = []; + +for (const file of snaps) { + const spec = file.replace(/-snapshots\/[^\/]+$/, ''); + const name = path.basename(file); + const stem = name.replace(/-\d+\.png$/, '').replace(/\.png$/, ''); + if (!fs.existsSync(spec)) { + unused.push(file); + continue; + } + const stripped = fs.readFileSync(spec, 'utf8').replace(/\/\/.*|\/\*[\s\S]*?\*\//g, ''); + if (!stripped.includes(name) && !stripped.includes(stem)) unused.push(file); +} + +if (unused.length) { + if (process.argv.includes('--prune')) { + for (const f of unused) fs.rmSync(f); + const dirs = [...new Set(unused.map((f) => path.dirname(f)))]; + for (const d of dirs) if (!fs.readdirSync(d).length) fs.rmdirSync(d); + console.log(`Removed unused snapshots:\n${unused.join('\n')}`); + } else { + console.error(`Unused snapshots:\n${unused.join('\n')}`); + process.exit(1); + } +} else { + console.log('No unused snapshots found'); +}