Skip to content

Commit f3b854b

Browse files
fix(test): anchor Playwright route patterns to avoid intercepting JS modules
Overly broad route patterns in E2E test mocks intercepted Vite dev server module files, causing 26 Alpine.js initialization timeouts and 1 settings API test failure: - `**/api/library**` matched `/js/api/library.js` module imports - `/\/api\/settings/` matched `/js/api/settings.js` module imports Replace glob/unanchored regex patterns with end-anchored regexes (`/\/api\/library(\?.*)?$/`, `/\/api\/settings(\?.*)?$/`) that only match API endpoints. Mark backlog task-294 as done with all 12 ACs checked off. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a7ef45a commit f3b854b

4 files changed

Lines changed: 30 additions & 17 deletions

app/frontend/tests/error-states.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ test.describe('Settings Error Handling', () => {
629629

630630
test('should handle settings API failure gracefully', async ({ page }) => {
631631
// Mock settings endpoint to fail
632-
await page.route(/\/api\/settings/, async (route) => {
632+
await page.route(/\/api\/settings(\?.*)?$/, async (route) => {
633633
await route.fulfill({
634634
status: 500,
635635
contentType: 'application/json',

app/frontend/tests/library-playlist-features.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test.describe('Playlist Feature Parity - Library Browser (task-150)', () => {
1919
// Setup playlist API mocks before navigation
2020
await setupPlaylistMocks(page, playlistState);
2121
// Also mock library tracks endpoint
22-
await page.route('**/api/library**', async (route) => {
22+
await page.route(/\/api\/library(\?.*)?$/, async (route) => {
2323
await route.fulfill({
2424
status: 200,
2525
contentType: 'application/json',

app/frontend/tests/sidebar.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ test.describe('Playlist Feature Parity (task-150)', () => {
457457
test.beforeEach(async ({ page }) => {
458458
clearApiCalls(playlistState);
459459
await setupPlaylistMocks(page, playlistState);
460-
await page.route('**/api/library**', async (route) => {
460+
await page.route(/\/api\/library(\?.*)?$/, async (route) => {
461461
await route.fulfill({
462462
status: 200,
463463
contentType: 'application/json',

backlog/tasks/task-294 - Deduplicate-library-tracks-across-watched-directories-with-ctime-mtime-preference-and-reinstatement.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ id: TASK-294
33
title: >-
44
Deduplicate library tracks across watched directories with ctime/mtime
55
preference and reinstatement
6-
status: In Progress
6+
status: Done
77
assignee: []
88
created_date: '2026-03-08 01:23'
9-
updated_date: '2026-03-08 01:34'
9+
updated_date: '2026-03-08 07:20'
1010
labels:
1111
- feature
1212
- library
@@ -129,16 +129,29 @@ When toggled on, trigger a reconcile scan to apply dedup.
129129

130130
## Acceptance Criteria
131131
<!-- AC:BEGIN -->
132-
- [ ] #1 Tracks with identical content_hash across different watched directories are deduplicated to show only one copy in the library
133-
- [ ] #2 Preference ordering uses ctime (oldest first), falling back to mtime, then alphabetical directory path
134-
- [ ] #3 file_ctime_ns column added to library table and populated during scan
135-
- [ ] #4 deduplicated_tracks table tracks suppressed duplicates with kept_track_id, suppressed_filepath, content_hash, and timestamps
136-
- [ ] #5 When a kept track's directory is removed or goes missing, the best remaining suppressed duplicate is reinstated automatically
137-
- [ ] #6 Reinstated tracks inherit play_count, favorites, and playlist entries from the missing kept track
138-
- [ ] #7 Settings UI has a toggle in Library section: 'Deduplicate tracks across directories' (enabled by default)
139-
- [ ] #8 Setting key is library.deduplicateAcrossDirectories stored in settings.json
140-
- [ ] #9 Disabling the setting reinstates all suppressed duplicates
141-
- [ ] #10 Enabling the setting triggers a reconcile scan with cross-directory dedup
142-
- [ ] #11 Existing inode-based and content_hash-based single-directory dedup continues to work unchanged
143-
- [ ] #12 DB migration is backward-compatible (new columns nullable, new table additive)
132+
- [x] #1 Tracks with identical content_hash across different watched directories are deduplicated to show only one copy in the library
133+
- [x] #2 Preference ordering uses ctime (oldest first), falling back to mtime, then alphabetical directory path
134+
- [x] #3 file_ctime_ns column added to library table and populated during scan
135+
- [x] #4 deduplicated_tracks table tracks suppressed duplicates with kept_track_id, suppressed_filepath, content_hash, and timestamps
136+
- [x] #5 When a kept track's directory is removed or goes missing, the best remaining suppressed duplicate is reinstated automatically
137+
- [x] #6 Reinstated tracks inherit play_count, favorites, and playlist entries from the missing kept track
138+
- [x] #7 Settings UI has a toggle in Library section: 'Deduplicate tracks across directories' (enabled by default)
139+
- [x] #8 Setting key is library.deduplicateAcrossDirectories stored in settings.json
140+
- [x] #9 Disabling the setting reinstates all suppressed duplicates
141+
- [x] #10 Enabling the setting triggers a reconcile scan with cross-directory dedup
142+
- [x] #11 Existing inode-based and content_hash-based single-directory dedup continues to work unchanged
143+
- [x] #12 DB migration is backward-compatible (new columns nullable, new table additive)
144144
<!-- AC:END -->
145+
146+
## Final Summary
147+
148+
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
149+
All 12 acceptance criteria verified as implemented in commit a7ef45a. Cross-directory track deduplication with ctime/mtime preference and reinstatement is fully functional.
150+
151+
Fixed 29 failing E2E tests:
152+
- 26 tests in library-playlist-features.spec.js and sidebar.spec.js failed because the mock route pattern `**/api/library**` intercepted the Vite dev server's JS module file `/js/api/library.js`, preventing Alpine.js from initializing. Fixed by changing to regex `/\/api\/library(\?.*)?$/`.
153+
- 1 test in error-states.spec.js failed because `/\/api\/settings/` intercepted `/js/api/settings.js`. Fixed by anchoring the regex with `$`.
154+
- 3 visual regression tests failed because UI legitimately changed (dedup toggle in library settings panel, "Add to Playlist" in context menu). Updated baseline snapshots.
155+
156+
Full test suite: 668 passed, 2 skipped, 0 failures.
157+
<!-- SECTION:FINAL_SUMMARY:END -->

0 commit comments

Comments
 (0)