Skip to content

Commit 8420299

Browse files
authored
Tests for abc.js (#4385)
* prompt user * test suites for abc.js * tests for abc.js * test suites for abc.js * tests for abc.js * no space after note
1 parent 75349f9 commit 8420299

File tree

2 files changed

+149
-21
lines changed

2 files changed

+149
-21
lines changed

js/__tests__/abc.test.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Mock global constants
2+
global.NOTATIONNOTE = 0;
3+
global.NOTATIONDURATION = 1;
4+
global.NOTATIONDOTCOUNT = 2;
5+
global.NOTATIONTUPLETVALUE = 3;
6+
global.NOTATIONROUNDDOWN = 4;
7+
global.NOTATIONINSIDECHORD = 5; // deprecated
8+
global.NOTATIONSTACCATO = 6;
9+
10+
global.frequencyToPitch = jest.fn((freq) => ["G♯", "4"]);
11+
global.toFraction = jest.fn((num) => [1, 1]);
12+
13+
const { getABCHeader, processABCNotes, saveAbcOutput, ACCIDENTAL_MAP, OCTAVE_NOTATION_MAP } = require('../abc');
14+
15+
describe('getABCHeader', () => {
16+
it('should return the correct ABC header', () => {
17+
const expectedHeader = "X:1\nT:Music Blocks composition\nC:Mr. Mouse\nL:1/16\nM:C\n";
18+
expect(getABCHeader()).toBe(expectedHeader);
19+
});
20+
});
21+
22+
describe('processABCNotes', () => {
23+
let logo;
24+
25+
beforeEach(() => {
26+
logo = {
27+
notationNotes: { "0": "" },
28+
notation: {
29+
notationStaging: {
30+
"0": [
31+
[["G♯4"], 4, 0, null, null, -1, false],
32+
[["F4"], 4, 0, null, null, -1, false],
33+
[["G♯4"], 2, 0, null, null, -1, false],
34+
],
35+
},
36+
},
37+
};
38+
});
39+
40+
it('should process notes and update notationNotes correctly', () => {
41+
processABCNotes(logo, "0");
42+
expect(logo.notationNotes["0"]).toBe("G^4 G^4 F4 F4 G^2 G^8 ");
43+
});
44+
});
45+
46+
describe('saveAbcOutput', () => {
47+
let activity;
48+
49+
beforeEach(() => {
50+
activity = {
51+
logo: {
52+
notationOutput: "",
53+
notationNotes: { "0": "" },
54+
notation: {
55+
notationStaging: {
56+
"0": [
57+
[["G♯4"], 4, 0, null, null, -1, false],
58+
[["F4"], 4, 0, null, null, -1, false],
59+
[["G♯4"], 2, 0, null, null, -1, false],
60+
],
61+
},
62+
},
63+
},
64+
turtles: {
65+
ithTurtle: (t) => ({
66+
singer: {
67+
keySignature: "C major",
68+
},
69+
}),
70+
},
71+
};
72+
});
73+
74+
it('should generate the correct ABC notation output', () => {
75+
const expectedOutput ="X:1\n"+
76+
"T:Music Blocks composition\n"+
77+
"C:Mr. Mouse\n"+
78+
"L:1/16\n"+
79+
"M:C\n"+
80+
"K:CMAJOR\n"+
81+
"G^4 G^4 F4 F4 G^2 G^8 \n";
82+
83+
const result = saveAbcOutput(activity);
84+
expect(result).toBe(expectedOutput);
85+
});
86+
});
87+
88+
describe('processABCNotes - Tuplet Handling', () => {
89+
it('should process tuplets correctly', () => {
90+
const logo = {
91+
notationNotes: { "0": "" },
92+
notation: {
93+
notationStaging: {
94+
"0": [
95+
[["G♯4"], 4, 0, 3, 2, -1, false], // Tuplet
96+
[["F4"], 4, 0, 3, 2, -1, false], // Tuplet
97+
[["G♯4"], 4, 0, 3, 2, -1, false], // Tuplet
98+
],
99+
},
100+
},
101+
};
102+
103+
processABCNotes(logo, "0");
104+
expect(logo.notationNotes["0"]).toBe("(1:1G^ 2G^ 2G^ 2 ");
105+
});
106+
});
107+
108+
describe("OCTAVE_NOTATION_MAP", () => {
109+
it("should correctly map octaves to ABC notation", () => {
110+
expect(OCTAVE_NOTATION_MAP[10]).toBe("'''''");
111+
expect(OCTAVE_NOTATION_MAP[2]).toBe(",,");
112+
expect(OCTAVE_NOTATION_MAP[1]).toBe(",,,");
113+
expect(OCTAVE_NOTATION_MAP[0]).toBeUndefined();
114+
});
115+
});
116+
117+
describe("ACCIDENTAL_MAP", () => {
118+
test("should correctly map accidentals to ABC notation", () => {
119+
expect(ACCIDENTAL_MAP["♯"]).toBe("^");
120+
expect(ACCIDENTAL_MAP["♭"]).toBe("_");
121+
});
122+
123+
test("should return undefined for unmapped accidentals", () => {
124+
expect(ACCIDENTAL_MAP["♮"]).toBeUndefined();
125+
});
126+
});

js/abc.js

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,23 @@
2121

2222
// This header is prepended to the Abc output.
2323
const ABCHEADER = "X:1\nT:Music Blocks composition\nC:Mr. Mouse\nL:1/16\nM:C\n";
24+
const OCTAVE_NOTATION_MAP = {
25+
10: "'''''",
26+
9: "''''",
27+
8: "'''",
28+
7: "''",
29+
6: "'",
30+
5: "",
31+
4: "",
32+
3: ",",
33+
2: ",,",
34+
1: ",,,"
35+
};
36+
37+
const ACCIDENTAL_MAP = {
38+
"♯": "^",
39+
"♭": "_"
40+
};
2441

2542
/**
2643
* Returns the header string used for the ABC notation output.
@@ -65,24 +82,6 @@ const processABCNotes = function(logo, turtle) {
6582
// Also, notes must be lowercase.
6683
// And the octave bounday is at C, not A.
6784

68-
const OCTAVE_NOTATION_MAP = {
69-
10: "'''''",
70-
9: "''''",
71-
8: "'''",
72-
7: "''",
73-
6: "'",
74-
5: "",
75-
4: "",
76-
3: ",",
77-
2: ",,",
78-
1: ",,,"
79-
};
80-
81-
const ACCIDENTAL_MAP = {
82-
"♯": "^",
83-
"♭": "_"
84-
};
85-
8685
// Handle frequency conversion
8786
if (typeof note === "number") {
8887
const pitchObj = frequencyToPitch(note);
@@ -105,7 +104,7 @@ const processABCNotes = function(logo, turtle) {
105104
// Convert case based on octave
106105
return note.includes("'") || note === "" ? note.toLowerCase() : note.toUpperCase();
107106
};
108-
107+
109108
let counter = 0;
110109
let queueSlur = false;
111110
let articulation = false;
@@ -335,7 +334,6 @@ const processABCNotes = function(logo, turtle) {
335334

336335
for (let ii = 0; ii < notes.length; ii++) {
337336
logo.notationNotes[turtle] += __toABCnote(notes[ii]);
338-
logo.notationNotes[turtle] += " ";
339337
}
340338

341339
if (notes.length > 1) {
@@ -444,4 +442,8 @@ const saveAbcOutput = function(activity) {
444442

445443
activity.logo.notationOutput += "\n";
446444
return activity.logo.notationOutput;
447-
};
445+
};
446+
447+
if (typeof module !== 'undefined' && module.exports) {
448+
module.exports = { getABCHeader, processABCNotes, saveAbcOutput, ACCIDENTAL_MAP, OCTAVE_NOTATION_MAP };
449+
}

0 commit comments

Comments
 (0)