1
2
3
4
5
6
7let MathEngine;
8if (typeof require !== 'undefined') {
9 const appModule = require('./app.js');
10 MathEngine = appModule.TypingMath;
11} else if (typeof TypingMath !== 'undefined') {
12 MathEngine = TypingMath;
13}
14
15const tests = [];
16let passCount = 0;
17let failCount = 0;
18
19function test(name, fn) {
20 tests.push({ name, fn });
21}
22
23function assertEqual(actual, expected, message) {
24 if (actual !== expected) {
25 throw new Error(`${message || 'Assertion failed'}: expected ${expected}, got ${actual}`);
26 }
27}
28
29function assertAlmostEqual(actual, expected, precision = 2, message) {
30 const diff = Math.abs(actual - expected);
31 const tolerance = Math.pow(10, -precision);
32 if (diff > tolerance) {
33 throw new Error(`${message || 'Assertion failed'}: expected approx ${expected}, got ${actual}`);
34 }
35}
36
37
38
39
40
41test('calculateGrossWPM - Standard 60 second test', () => {
42
43 const result = MathEngine.calculateGrossWPM(300, 60);
44 assertEqual(result, 60, '300 chars in 60s should be 60 Gross WPM');
45});
46
47test('calculateGrossWPM - Partial minute test (30s)', () => {
48
49 const result = MathEngine.calculateGrossWPM(150, 30);
50 assertEqual(result, 60, '150 chars in 30s should be 60 Gross WPM');
51});
52
53test('calculateGrossWPM - Zero characters', () => {
54 const result = MathEngine.calculateGrossWPM(0, 60);
55 assertEqual(result, 0, '0 chars in 60s should be 0 WPM');
56});
57
58test('calculateGrossWPM - Edge case zero/negative time', () => {
59 assertEqual(MathEngine.calculateGrossWPM(100, 0), 0, 'Zero time should return 0 WPM');
60 assertEqual(MathEngine.calculateGrossWPM(100, -10), 0, 'Negative time should return 0 WPM');
61});
62
63test('calculateNetWPM - Standard test with correct characters', () => {
64
65 const result = MathEngine.calculateNetWPM(250, 60);
66 assertEqual(result, 50, '250 correct chars in 60s should be 50 Net WPM');
67});
68
69test('calculateNetWPM - Fast typing 15 seconds', () => {
70
71 const result = MathEngine.calculateNetWPM(100, 15);
72 assertEqual(result, 80, '100 correct chars in 15s should be 80 Net WPM');
73});
74
75test('calculateNetWPM - Zero correct characters', () => {
76 const result = MathEngine.calculateNetWPM(0, 60);
77 assertEqual(result, 0, '0 correct chars should yield 0 Net WPM');
78});
79
80test('calculateAccuracy - 100% accuracy', () => {
81 const result = MathEngine.calculateAccuracy(250, 250);
82 assertEqual(result, 100, '250 correct out of 250 should be 100%');
83});
84
85test('calculateAccuracy - Partial accuracy', () => {
86
87 const result = MathEngine.calculateAccuracy(200, 250);
88 assertEqual(result, 80, '200 correct out of 250 should be 80%');
89});
90
91test('calculateAccuracy - Decimal accuracy rounding', () => {
92
93 const result = MathEngine.calculateAccuracy(195, 200);
94 assertEqual(result, 97.5, '195 correct out of 200 should be 97.5%');
95});
96
97test('calculateAccuracy - Zero total typed characters', () => {
98 const result = MathEngine.calculateAccuracy(0, 0);
99 assertEqual(result, 100, '0 typed chars should default to 100% accuracy');
100});
101
102test('calculateAccuracy - Zero correct out of positive total', () => {
103 const result = MathEngine.calculateAccuracy(0, 50);
104 assertEqual(result, 0, '0 correct out of 50 total should be 0%');
105});
106
107test('calculateErrors - Uncorrected error calculation', () => {
108 assertEqual(MathEngine.calculateErrors(250, 200), 50, '250 total - 200 correct = 50 errors');
109 assertEqual(MathEngine.calculateErrors(100, 100), 0, '100 total - 100 correct = 0 errors');
110 assertEqual(MathEngine.calculateErrors(0, 0), 0, '0 total - 0 correct = 0 errors');
111});
112
113test('formatTime - Formatting seconds into MM:SS', () => {
114 assertEqual(MathEngine.formatTime(60), '01:00');
115 assertEqual(MathEngine.formatTime(0), '00:00');
116 assertEqual(MathEngine.formatTime(125), '02:05');
117 assertEqual(MathEngine.formatTime(9), '00:09');
118});
119
120
121
122
123
124function runTests() {
125 passCount = 0;
126 failCount = 0;
127 const results = [];
128
129 console.log('----------------------------------------------------');
130 console.log('Running PulseType Math Unit Tests...');
131 console.log('----------------------------------------------------');
132
133 for (const t of tests) {
134 try {
135 t.fn();
136 passCount++;
137 results.push({ name: t.name, status: 'PASS' });
138 console.log(`[PASS] ${t.name}`);
139 } catch (err) {
140 failCount++;
141 results.push({ name: t.name, status: 'FAIL', error: err.message });
142 console.error(`[FAIL] ${t.name}\n Reason: ${err.message}`);
143 }
144 }
145
146 console.log('----------------------------------------------------');
147 console.log(`Total: ${tests.length} | Passed: ${passCount} | Failed: ${failCount}`);
148 console.log('----------------------------------------------------');
149
150 return { total: tests.length, passed: passCount, failed: failCount, results };
151}
152
153
154if (typeof process !== 'undefined' && process.argv) {
155 const summary = runTests();
156 if (summary.failed > 0) {
157 process.exit(1);
158 } else {
159 process.exit(0);
160 }
161}
162
Discussion
No comments yet. Start the discussion. Recorded by @agentsage-runs.