dex/test/formTracking.test.js
chris bbc4cb48ca Save import: read the Gen 2 Unown Report
Gen 2 (GSC) is the one mainline dex that records which Unown letters
you've caught — a 26-byte ordered list right after the Seen flag array
(seen + 0x20). Parse it, map letters to the app's Form Dex slugs
('unown' for A, 'unown-b'…'unown-z'), and tick them via a new
markFormsCaught() on the formTracking store. A garbage/out-of-range list
is ignored rather than guessed at.

The import dialog and result line now surface "· N Unown letters".

Verified: 6 new unit tests (synthetic Gen 2 SRAM → slugs, empty list,
garbage rejection; markFormsCaught behaviour) + a real end-to-end import
of a synthetic Crystal save writing {unown, unown-c, unown-o, unown-z}
to pdx.formTracking.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ve7HLspzeG2xDPtJQ8vmu
2026-09-10 12:21:41 -04:00

38 lines
1.1 KiB
JavaScript

import { describe, it, expect, beforeEach } from 'vitest';
import {
formTracking,
isFormCaught,
toggleFormCaught,
markFormsCaught,
} from '../src/store/formTracking.js';
beforeEach(() => {
localStorage.clear();
formTracking.replace({ caught: {} });
});
describe('formTracking', () => {
it('toggle flips a slug', () => {
expect(isFormCaught('unown-c')).toBe(false);
toggleFormCaught('unown-c');
expect(isFormCaught('unown-c')).toBe(true);
toggleFormCaught('unown-c');
expect(isFormCaught('unown-c')).toBe(false);
});
it('markFormsCaught sets a batch and never un-marks', () => {
toggleFormCaught('unown-z'); // already caught
markFormsCaught(['unown', 'unown-c', 'unown-z']);
expect(isFormCaught('unown')).toBe(true);
expect(isFormCaught('unown-c')).toBe(true);
expect(isFormCaught('unown-z')).toBe(true); // stays caught
expect(isFormCaught('unown-q')).toBe(false); // untouched
});
it('markFormsCaught tolerates empty / missing input', () => {
markFormsCaught([]);
markFormsCaught(undefined);
expect(formTracking.get().caught).toEqual({});
});
});