Skip to content

Commit f5800b5

Browse files
committed
test: add unit tests for statistics.js (Clean)
1 parent e4219ba commit f5800b5

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

js/widgets/statistics.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,6 @@ class StatsWindow {
116116
<li>ornaments used: ${stats["ornaments"]}</li>`;
117117
}
118118
}
119+
if (typeof module !== "undefined") {
120+
module.exports = StatsWindow;
121+
}

js/widgets/statistics.test.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
const StatsWindow = require("./statistics.js");
2+
3+
describe("StatsWindow", () => {
4+
let mockActivity;
5+
let mockWidgetWindow;
6+
7+
beforeEach(() => {
8+
// 1. Mock the Activity object
9+
mockActivity = {
10+
blocks: { showBlocks: jest.fn(), hideBlocks: jest.fn(), activeBlock: null },
11+
logo: { statsWindow: null },
12+
loading: false,
13+
showBlocksAfterRun: true
14+
};
15+
16+
// 2. Mock the Widget Window
17+
mockWidgetWindow = {
18+
clear: jest.fn(),
19+
show: jest.fn(),
20+
destroy: jest.fn(),
21+
sendToCenter: jest.fn(),
22+
onclose: null,
23+
onmaximize: null,
24+
getWidgetBody: jest.fn().mockReturnValue(document.createElement("div")),
25+
getWidgetFrame: jest
26+
.fn()
27+
.mockReturnValue({ getBoundingClientRect: () => ({ height: 500 }) }),
28+
isMaximized: jest.fn().mockReturnValue(false)
29+
};
30+
31+
// 3. Mock window.widgetWindows
32+
window.widgetWindows = {
33+
windowFor: jest.fn().mockReturnValue(mockWidgetWindow)
34+
};
35+
36+
// 4. CRITICAL FIX: Mock docById to return a fake Canvas with getContext
37+
global.docById = jest.fn().mockReturnValue({
38+
getContext: jest.fn().mockReturnValue({
39+
// Fake context methods if needed (not strictly needed for this test)
40+
})
41+
});
42+
43+
// 5. Mock external analysis functions (global scope)
44+
global.analyzeProject = jest.fn().mockReturnValue({});
45+
global.runAnalytics = jest.fn();
46+
global.scoreToChartData = jest.fn().mockReturnValue({});
47+
global.getChartOptions = jest.fn().mockReturnValue({});
48+
49+
// Mock the Chart.js library
50+
global.Chart = jest.fn().mockImplementation(() => ({
51+
Radar: jest.fn()
52+
}));
53+
});
54+
55+
test("displayInfo should correctly format note statistics and Hz calculations", () => {
56+
const statsWindow = new StatsWindow(mockActivity);
57+
58+
// Prepare dummy data
59+
const mockStats = {
60+
duples: 5,
61+
triplets: 2,
62+
quintuplets: 0,
63+
pitchNames: new Set(["A", "C#", "E"]),
64+
numberOfNotes: 20,
65+
lowestNote: ["A4", 60, 440],
66+
highestNote: ["C5", 72, 523.25],
67+
rests: 4,
68+
ornaments: 1
69+
};
70+
71+
// Run the function
72+
statsWindow.displayInfo(mockStats);
73+
74+
// Check results
75+
const outputHtml = statsWindow.jsonObject.innerHTML;
76+
77+
expect(outputHtml).toContain("441Hz"); // 440 + 0.5 rounded
78+
expect(outputHtml).toContain("524Hz"); // 523.25 + 0.5 rounded
79+
expect(outputHtml).toContain("duples: 5");
80+
expect(outputHtml).toContain("triplets: 2");
81+
expect(outputHtml).toContain("pitch names: A, C#, E");
82+
});
83+
});

0 commit comments

Comments
 (0)