feedBack/tests/browser
Byron Gamatos a791a0d8fe
feat(v3): DOM-virtualize the Songs grid (#636 item 3 stage 2) (#643)
The v3 Songs grid appended every scrolled page and never released nodes,
so card-node count grew unbounded with scroll depth (24 → 624 → 2001 for a
2000-song library). Replace it with a windowed/recycled render: only the
visible window (± overscan) is in the DOM while a #v3-songs-gridsizer
element sized to ceil(total/cols)*rowH gives the scrollbar full-library
geometry; #v3-songs-grid is absolutely positioned to the first visible row.

- state.songs is a sparse, absolutely-indexed store filled a page at a time
  by ensureWindow(): the stage-1 keyset cursor for contiguous forward scroll
  (O(page)), OFFSET page= for jumps/restore/non-keyset providers. _loadPage
  shares an in-flight promise per page and an epoch guard discards a stale
  fetch that lands after a reset.
- A–Z rail seeks directly via sort_letters cumulative counts (O(1), no
  page-through); bounded scan fallback for legacy providers without it.
- Snapshot/restore is now scrollTop-based (geometry is stable). Select mode,
  accuracy badges, ⋮ menu, plugin card actions, and tree/folder coexistence
  survive cards recycling; renderWindow re-renders when select mode toggles.
- Plugins get window.v3Songs.visibleCards() + a v3:library-window-rendered
  event instead of assuming all cards are present (highway-stutter lesson).

Verified in a browser against a seeded 2001-song library: DOM bounded to
~60 nodes while the count reads "2001 songs", rail jump lands on the target
row, selection survives recycling, scroll-restore exact. Codex-reviewed
(3 findings fixed: stale-fetch epoch guard, await-in-flight page promise,
select-mode resync on cached re-entry).

Frontend-only. Tests: tests/browser/v3-grid-virtualization.spec.ts pins the
bounded-DOM invariant + direct rail jump; tests/js/v3_az_rail.test.js and
v3_songs_scroll.test.js updated to the new wiring.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 12:26:29 +02:00
..
audio-session-compat.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
audio-session.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
basic-load.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
capability-inspector.spec.ts Clean release snapshot 2026-06-16 18:47:13 +02:00
check-errors.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
default-arrangement-pin.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
exit-confirm.spec.ts fix(player): reliable Escape "Back" + resumable, optionally-confirmed song exit (#619) 2026-06-28 12:32:33 +02:00
highway-3d-lefty.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
keyboard-shortcuts.spec.ts fix(player): reliable Escape "Back" + resumable, optionally-confirmed song exit (#619) 2026-06-28 12:32:33 +02:00
progress-shop.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
README.md rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00
resume-session.spec.ts fix(player): reliable Escape "Back" + resumable, optionally-confirmed song exit (#619) 2026-06-28 12:32:33 +02:00
settings-tabbed.spec.ts feat(v3): tabbed, card-row settings page + per-plugin settings category (#584) 2026-06-23 18:06:46 +02:00
v3-grid-virtualization.spec.ts feat(v3): DOM-virtualize the Songs grid (#636 item 3 stage 2) (#643) 2026-06-29 12:26:29 +02:00
v3-section-map-leftmost-click.spec.ts fix(v3): keep Section Map's leftmost section clickable under the rail catcher (#617) 2026-06-27 21:07:44 +02:00
v3-tree-select.spec.ts Fix list/tree view: select mode, parts visibility, song actions (#585) 2026-06-24 21:49:02 +02:00
wake-lock.spec.ts rename: slopsmith → feedBack, byron → got-feedBack (#537) 2026-06-23 11:03:01 +02:00

Browser Tests

This directory contains Playwright browser tests for FeedBack keyboard shortcuts.

Prerequisites

  1. FeedBack web server: Tests need the server reachable at http://localhost:8000. Playwright auto-starts it via webServer.command in playwright.config.ts, so manual startup is optional. Start it manually if you want to debug the server, run tests outside Playwright, or skip the per-run boot delay:

    LIBRARY_PATH=/path/to/your/library docker compose up -d
    

    Playwright reuses an already-running server locally (reuseExistingServer: true).

  2. Node.js installed: Required for running Playwright tests

    node --version  # Should be v18 or higher
    

Installation

Install dependencies:

npm install

Install Playwright browsers:

npm run install:playwright

Running Tests

Run all tests:

npm test

Run tests in headed mode (watch the browser):

npm run test:headed

Debug tests with interactive inspector:

npm run test:debug

Test Files

  • basic-load.spec.ts - Basic app load and shortcut registry availability
  • check-errors.spec.ts - Check for console errors
  • keyboard-shortcuts.spec.ts - Comprehensive keyboard shortcut tests

Writing Tests

Tests use Playwright's test API. Example:

import { test, expect } from '@playwright/test';

test('my test', async ({ page }) => {
  await page.goto('/');
  await page.waitForSelector('.screen.active');
  
  // Interact with the page
  await page.keyboard.press('?');
  
  // Assert
  await expect(page.locator('#shortcuts-modal')).toBeVisible();
});

Troubleshooting

Container won't start

If the Docker container exits immediately, check the logs:

docker compose logs

Common issue: Missing dependencies. Rebuild the container:

docker compose build --no-cache
docker compose up -d

Tests timeout

Increase timeout in playwright.config.ts if needed.

LIBRARY_PATH not set

Make sure to set the LIBRARY_PATH environment variable:

LIBRARY_PATH=~/feedBack-library docker compose up -d

CI/CD

In CI environments, Playwright will:

  • Run tests in headless mode
  • Retry failed tests up to 2 times
  • Generate HTML report with screenshots/videos on failure