// Reads of a store property that does not exist. // // JavaScript returns `undefined` for a missing property instead of failing, and // the frontend CI has no type-checker to catch it. `platformsStore.platforms` // was read for months by the Latest feed's filter bar and the Artists view. The // store exposes `list` and `byKey`, so both platform dropdowns opened empty and // only someone clicking them noticed. // // This scans the source for `platformsStore.` and checks each name // against what the store really defines. import { readdirSync, readFileSync, statSync } from 'node:fs' import { join } from 'node:path' import { fileURLToPath } from 'node:url' import { createPinia, setActivePinia } from 'pinia' import { describe, expect, it } from 'vitest' import { usePlatformsStore } from '../src/stores/platforms.js' const SRC = fileURLToPath(new URL('../src', import.meta.url)) const READ = /\bplatformsStore\.([A-Za-z_$][\w$]*)/g function sourceFiles (dir) { return readdirSync(dir).flatMap((name) => { const path = join(dir, name) if (statSync(path).isDirectory()) return sourceFiles(path) return /\.(vue|js)$/.test(name) ? [path] : [] }) } function unknownReads (text, known) { return [...text.matchAll(READ)].map(m => m[1]).filter(name => !known.has(name)) } function storeKeys () { setActivePinia(createPinia()) return new Set(Object.keys(usePlatformsStore())) } describe('platforms store usage', () => { it('every platformsStore. read in src names something the store defines', () => { const known = storeKeys() const offenders = sourceFiles(SRC).flatMap((file) => unknownReads(readFileSync(file, 'utf8'), known) .map(name => `${file.slice(SRC.length + 1)}: platformsStore.${name}`), ) expect(offenders).toEqual([]) }) it('the scan finds the read that shipped broken (positive control)', () => { const known = storeKeys() expect(known.has('list')).toBe(true) expect(unknownReads('(platformsStore.platforms || []).map(p => p)', known)) .toEqual(['platforms']) }) it('the scan actually walks the source tree', () => { const hasRead = /\bplatformsStore\./ const withReads = sourceFiles(SRC).filter(f => hasRead.test(readFileSync(f, 'utf8'))) expect(withReads.length).toBeGreaterThan(2) }) })