vexflow
Version:
A JavaScript library for rendering music notation and guitar tablature.
162 lines (161 loc) • 7.8 kB
JavaScript
import { VexFlowTests } from './vexflow_test_helpers.js';
import { KeyManager } from '../src/keymanager.js';
import { Music } from '../src/music.js';
const MusicTests = {
Start() {
QUnit.module('MusicTests');
QUnit.test('Valid Notes', validNotes);
QUnit.test('Valid Keys', validKeys);
QUnit.test('Note Values', noteValue);
QUnit.test('Interval Values', intervalValue);
QUnit.test('Relative Notes', relativeNotes);
QUnit.test('Relative Note Names', relativeNoteNames);
QUnit.test('Canonical Notes', canonicalNotes);
QUnit.test('Canonical Intervals', canonicalIntervals);
QUnit.test('Scale Tones', scaleTones);
QUnit.test('Scale Intervals', scaleIntervals);
},
};
function validNotes(assert) {
assert.expect(10);
const music = new Music();
let parts = music.getNoteParts('c');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, null);
parts = music.getNoteParts('C');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, null);
parts = music.getNoteParts('c#');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, '#');
parts = music.getNoteParts('c##');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, '##');
assert.throws(() => music.getNoteParts('r'), /BadArguments/, 'Invalid note: r');
assert.throws(() => music.getNoteParts(''), /BadArguments/, "Invalid note: ''");
}
function validKeys(assert) {
assert.expect(18);
const music = new Music();
let parts = music.getKeyParts('c');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, null);
assert.equal(parts.type, 'M');
parts = music.getKeyParts('d#');
assert.equal(parts.root, 'd');
assert.equal(parts.accidental, '#');
assert.equal(parts.type, 'M');
parts = music.getKeyParts('fbm');
assert.equal(parts.root, 'f');
assert.equal(parts.accidental, 'b');
assert.equal(parts.type, 'm');
parts = music.getKeyParts('c#mel');
assert.equal(parts.root, 'c');
assert.equal(parts.accidental, '#');
assert.equal(parts.type, 'mel');
parts = music.getKeyParts('g#harm');
assert.equal(parts.root, 'g');
assert.equal(parts.accidental, '#');
assert.equal(parts.type, 'harm');
assert.throws(() => music.getKeyParts('r'), /BadArguments/, 'Invalid key: r');
assert.throws(() => music.getKeyParts(''), /BadArguments/, `Invalid key: ''`);
assert.throws(() => music.getKeyParts('#m'), /BadArguments/, 'Invalid key: #m');
}
function noteValue(assert) {
assert.expect(3);
const music = new Music();
let note = music.getNoteValue('c');
assert.equal(note, 0);
assert.throws(() => music.getNoteValue('r'), /BadArguments/, 'Invalid note name');
note = music.getNoteValue('f#');
assert.equal(note, 6);
}
function intervalValue(assert) {
assert.expect(2);
const music = new Music();
const value = music.getIntervalValue('b2');
assert.equal(value, 1);
assert.throws(() => music.getIntervalValue('7'), /BadArguments/, 'Invalid interval name');
}
function relativeNotes(assert) {
assert.expect(8);
const music = new Music();
let value = music.getRelativeNoteValue(music.getNoteValue('c'), music.getIntervalValue('b5'));
assert.equal(value, 6);
assert.throws(() => music.getRelativeNoteValue(music.getNoteValue('bc'), music.getIntervalValue('b2')), /BadArguments/, 'Invalid note');
assert.throws(() => music.getRelativeNoteValue(music.getNoteValue('b'), music.getIntervalValue('p3')), /BadArguments/, 'Invalid interval');
value = music.getRelativeNoteValue(music.getNoteValue('d'), music.getIntervalValue('2'), -1);
assert.equal(value, 0);
assert.throws(() => music.getRelativeNoteValue(music.getNoteValue('b'), music.getIntervalValue('p4'), 0), /BadArguments/, 'Invalid direction: 0');
value = music.getRelativeNoteValue(music.getNoteValue('b'), music.getIntervalValue('b5'));
assert.equal(value, 5);
value = music.getRelativeNoteValue(music.getNoteValue('c'), music.getIntervalValue('b2'), -1);
assert.equal(value, 11);
value = music.getRelativeNoteValue(music.getNoteValue('g'), music.getIntervalValue('p5'));
assert.equal(value, 2);
}
function relativeNoteNames(assert) {
assert.expect(9);
const music = new Music();
assert.equal(music.getRelativeNoteName('b', music.getNoteValue('c#')), 'b##');
assert.equal(music.getRelativeNoteName('c', music.getNoteValue('c')), 'c');
assert.equal(music.getRelativeNoteName('c', music.getNoteValue('db')), 'c#');
assert.equal(music.getRelativeNoteName('c', music.getNoteValue('b')), 'cb');
assert.equal(music.getRelativeNoteName('c#', music.getNoteValue('db')), 'c#');
assert.equal(music.getRelativeNoteName('e', music.getNoteValue('f#')), 'e##');
assert.equal(music.getRelativeNoteName('e', music.getNoteValue('d#')), 'eb');
assert.equal(music.getRelativeNoteName('e', music.getNoteValue('fb')), 'e');
assert.throws(() => music.getRelativeNoteName('e', music.getNoteValue('g#')), /BadArguments/, 'Too far away. Notes not related.');
}
function canonicalNotes(assert) {
assert.expect(3);
const music = new Music();
assert.equal(music.getCanonicalNoteName(0), 'c');
assert.equal(music.getCanonicalNoteName(2), 'd');
assert.throws(() => music.getCanonicalNoteName(-1), /BadArguments/, 'Invalid note value');
}
function canonicalIntervals(assert) {
assert.expect(3);
const music = new Music();
assert.equal(music.getCanonicalIntervalName(0), 'unison');
assert.equal(music.getCanonicalIntervalName(2), 'M2');
assert.throws(() => music.getCanonicalIntervalName(-1), /BadArguments/, 'Invalid interval value');
}
function scaleTones(assert) {
assert.expect(24);
const music = new Music();
const manager = new KeyManager('CM');
const C_MAJOR = music.getScaleTones(music.getNoteValue('c'), Music.scales.major);
let values = ['c', 'd', 'e', 'f', 'g', 'a', 'b'];
assert.equal(C_MAJOR.length, 7);
for (let i = 0; i < C_MAJOR.length; ++i) {
assert.equal(music.getCanonicalNoteName(C_MAJOR[i]), values[i]);
}
const C_DORIAN = music.getScaleTones(music.getNoteValue('c'), Music.scales.dorian);
values = ['c', 'd', 'eb', 'f', 'g', 'a', 'bb'];
let note = null;
assert.equal(C_DORIAN.length, 7);
for (let i = 0; i < C_DORIAN.length; ++i) {
note = music.getCanonicalNoteName(C_DORIAN[i]);
assert.equal(manager.selectNote(note).note, values[i]);
}
const C_MIXOLYDIAN = music.getScaleTones(music.getNoteValue('c'), Music.scales.mixolydian);
values = ['c', 'd', 'e', 'f', 'g', 'a', 'bb'];
assert.equal(C_MIXOLYDIAN.length, 7);
for (let i = 0; i < C_MIXOLYDIAN.length; ++i) {
note = music.getCanonicalNoteName(C_MIXOLYDIAN[i]);
assert.equal(manager.selectNote(note).note, values[i]);
}
}
function scaleIntervals(assert) {
assert.expect(6);
const m = new Music();
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('c'), m.getNoteValue('d'))), 'M2');
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('g'), m.getNoteValue('c'))), 'p4');
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('c'), m.getNoteValue('c'))), 'unison');
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('f'), m.getNoteValue('cb'))), 'dim5');
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('d'), m.getNoteValue('c'), 1)), 'b7');
assert.equal(m.getCanonicalIntervalName(m.getIntervalBetween(m.getNoteValue('d'), m.getNoteValue('c'), -1)), 'M2');
}
VexFlowTests.register(MusicTests);
export { MusicTests };