mirror of
https://github.com/9x/sheetmusictrainer.git
synced 2026-11-03 22:03:54 +01:00
61 lines
2.5 KiB
TypeScript
61 lines
2.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { EXERCISES, findExercise, loadExercise } from './library';
|
|
import { validateScore, scoreEvents } from '../score/model';
|
|
|
|
describe('bundled exercise library', () => {
|
|
it('has a non-empty, uniquely-id\'d catalog', () => {
|
|
expect(EXERCISES.length).toBeGreaterThanOrEqual(4);
|
|
const ids = new Set(EXERCISES.map(e => e.id));
|
|
expect(ids.size).toBe(EXERCISES.length);
|
|
for (const ex of EXERCISES) {
|
|
expect(ex.label.length).toBeGreaterThan(0);
|
|
expect(ex.abc.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('every bundled file parses and validates', () => {
|
|
for (const ex of EXERCISES) {
|
|
const res = loadExercise(ex.id);
|
|
expect(res.ok, `${ex.id}: ${res.ok ? '' : res.error}`).toBe(true);
|
|
if (!res.ok) continue;
|
|
const problems = validateScore(res.value);
|
|
expect(problems, `${ex.id}: ${problems.join('; ')}`).toEqual([]);
|
|
expect(scoreEvents(res.value).length).toBeGreaterThan(0);
|
|
expect(res.value.title.length).toBeGreaterThan(0);
|
|
expect(res.value.source).toBeDefined();
|
|
expect(res.value.source!.rights.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('exercise sources declare provenance (composer or original)', () => {
|
|
for (const ex of EXERCISES) {
|
|
const res = loadExercise(ex.id);
|
|
if (!res.ok) continue;
|
|
const src = res.value.source!;
|
|
expect(src.composer || '').toBeTruthy();
|
|
expect(src.rights).toBeTruthy();
|
|
}
|
|
});
|
|
|
|
it('Ode to Joy theme has the expected note count and midis', () => {
|
|
const res = loadExercise('ode-to-joy');
|
|
expect(res.ok).toBe(true);
|
|
if (!res.ok) return;
|
|
const evts = scoreEvents(res.value);
|
|
expect(evts).toHaveLength(30); // two 4-bar phrases
|
|
expect(res.value.measures).toHaveLength(8);
|
|
// First phrase: E E F G G F E D C C D E
|
|
expect(evts.slice(0, 12).map(e => e.pitch!.midi)).toEqual([64, 64, 65, 67, 67, 65, 64, 62, 60, 60, 62, 64]);
|
|
// Bar 4 dotted rhythm: E3/2 D/2 D2 → 720, 240, 960
|
|
expect(evts[12].durationTicks).toBe(720);
|
|
expect(evts[13].durationTicks).toBe(240);
|
|
expect(evts[14].durationTicks).toBe(960);
|
|
});
|
|
|
|
it('unknown exercise ids fail cleanly', () => {
|
|
expect(loadExercise('nope').ok).toBe(false);
|
|
expect(findExercise('nope')).toBeUndefined();
|
|
expect(findExercise('ode-to-joy')?.id).toBe('ode-to-joy');
|
|
});
|
|
});
|