test: cover branches vitest 5 reports as uncovered (unblocks #91) - #93
vpetersson-bot wants to merge 2 commits into
Conversation
vitest 5 ships a stricter v8 coverage remapper. It counts 37 branches where vitest 3 counted 53, and it no longer credits branches that were never actually exercised, so branch coverage falls from 86.79% to 72.97% and trips the 80% global threshold in vitest.config.ts. The gap is real rather than a reporting artifact - these paths had no test at all: - assign-screen-to-playlist: perform() was never invoked (0% functions) - schedule-playlist-item: the missing-API-key guard and the is_new_asset branch that creates an asset first - complete-workflow: the missing-API-key guard, the existing-Zapier-label branch, and the `duration || 10` fallback - cleanup-zapier-content: the paths where a delete is rejected and the counter must not increment - utils: the empty-response guards in createAsset and createPlaylistItem, the 409 already-assigned branch and the non-409 error branch in assignPlaylistToScreen, and a failed deleteAsset Coverage goes to 100% statements, branches, functions and lines under both vitest 3.2.7 and vitest 5.0.1, so this stands on its own and does not depend on the bump landing first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟡 Changes recommended
Address the workflow response mock issue and strengthen the requested interceptor assertions.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds branch-focused tests to restore Vitest 5 coverage thresholds without changing production or dependency code.
Changes:
- Covers utility edge cases and failures.
- Adds scheduling, workflow, cleanup, and assignment scenarios.
- Adds tests for previously uncovered branches.
File summaries
| File | Summary |
|---|---|
test/utils.test.ts |
Tests utility edge cases and failures. |
test/schedule-playlist-item.test.ts |
Covers API-key and new-asset branches. |
test/complete-workflow.test.ts |
Covers label reuse and duration fallback. |
test/cleanup.test.ts |
Verifies rejected deletions are not counted. |
test/assign-screen-to-playlist.test.ts |
Adds assignment action coverage. |
Review details
Suppressed comments (2)
test/cleanup.test.ts:189
- The count assertions alone do not prove that the rejected delete requests were attempted: skipping the second playlist deletion and both asset deletion calls would still produce
1and0. Capture the delete interceptors and assert eachisDone()after the operation so this test actually exercises the failure-return paths it claims to cover.
expect(response.playlists_removed).toBe(1);
expect(response.assets_removed).toBe(0);
expect(response.message).toBe(
'Successfully removed 1 playlists and 0 assets'
);
test/complete-workflow.test.ts:300
- This mock returns an object, but
createPlaylistItemexpects the API response to be an array and readsitems[0]. Because the workflow does not inspect the returned item, this test can pass while the helper returnsundefined; use the same array-shaped response as the helper's contract.
.reply(201, { id: 'item-123' });
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Addresses Copilot review feedback on Screenly#93. createPlaylistItem reads items[0] from the response, so the nock mocks for /api/v4/playlist-items/ now reply with an array rather than a bare object. completeWorkflow ignores the returned item, so the old mocks passed while quietly handing the helper an undefined element. The existing-label test also only proved that label creation was skipped. It now keeps a handle on the labels/playlists interceptor for label-existing and asserts isDone(), so the test fails if the existing-label branch ever stops tagging the new playlist. Coverage stays at 100% on statements, branches, functions and lines under both vitest 3.2.7 and vitest 5.0.1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
Three unresolved review findings identify gaps in proving the intended mocked API requests were executed.
Review details
Suppressed comments (3)
Previously missed (1) — in code that hasn't changed since the last review.
test/cleanup.test.ts:186
- These count assertions do not prove that the rejected delete requests ran: skipping the asset loop entirely would still produce
assets_removed === 0, and stopping after the first playlist would still produceplaylists_removed === 1. The test can therefore pass without exercising the failure paths it is intended to cover; assert that all configured Nock interceptors were consumed (or keep handles and assertisDone()).
test/assign-screen-to-playlist.test.ts:46
- This assertion can pass even if the action returns a success object without issuing the assignment request, because the response fields are derived from the input. Assert that the configured interceptor was consumed so this test verifies that the API call actually occurred.
expect(response.message).toBe('Successfully assigned playlist to screen');
test/assign-screen-to-playlist.test.ts:70
- This test does not prove that the 409 response was consumed. If the action returned the success object without making a request, it would still pass, leaving the already-assigned branch untested. Assert that the interceptor was consumed.
expect(response.message).toBe('Successfully assigned playlist to screen');
- Files reviewed: 5/5 changed files
- Comments generated: 0 new
- Review effort level: Lite
Unblocks #91 (
vitest/@vitest/coverage-v83.x → 5.x), which fails CI with:Why it fails
Not a regression in the bump — vitest 5 ships a stricter v8 coverage remapper. It counts 37 branches where vitest 3 counted 53, and stops crediting branches that were never actually exercised. The threshold in
vitest.config.tsis unchanged; the measurement got honest.So the uncovered code is genuinely untested, not a reporting artifact. Every path below had no test at all:
assign-screen-to-playlistperform()was never invoked — 0% functionsschedule-playlist-itemis_new_assetbranch that uploads firstcomplete-workflowduration || 10fallbackcleanup-zapier-contentutilscreateAsset/createPlaylistItem; the 409 already-assigned and non-409 error branches inassignPlaylistToScreen; a faileddeleteAssetWhat this PR does
Adds 15 tests (one new file,
test/assign-screen-to-playlist.test.ts). Tests only — no source or dependency changes.Verification
Run on Node 22.23.2 against both versions:
npm run lint:check,npm run format:checkandnpm run buildall pass.Because it is clean on the currently pinned vitest 3 as well, it is safe to merge ahead of the bump —
masterstays green either way. Once this lands, #91 needs a@dependabot rebase(it is also currently conflicted onpackage-lock.jsonafter #92 merged) and should go green.Note, not addressed here
vitest 5 emits a forward-compat warning, harmless today:
Left alone since it is unrelated to the coverage gate — worth a follow-up when
configLoader: 'native'becomes Vite's default.🤖 Generated with Claude Code