Skip to content

Commit f6402e0

Browse files
committed
feat: add tests
1 parent d9056ad commit f6402e0

File tree

9 files changed

+846
-0
lines changed

9 files changed

+846
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This file will be duplicated for testing.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Test Page</title>
7+
<link rel="stylesheet" href="style.css" />
8+
</head>
9+
<body>
10+
<h1>Hello ESP32</h1>
11+
<p>This is a test page for SvelteESP32.</p>
12+
<script src="script.js"></script>
13+
</body>
14+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
This is a large file that should be compressed.
2+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
3+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
4+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
5+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
6+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
7+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
console.log('Hello from ESP32!');
2+
3+
document.addEventListener('DOMContentLoaded', () => {
4+
const heading = document.querySelector('h1');
5+
if (heading) {
6+
heading.style.color = '#007bff';
7+
}
8+
});
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
body {
2+
font-family: Arial, sans-serif;
3+
margin: 0;
4+
padding: 20px;
5+
background-color: #f0f0f0;
6+
}
7+
8+
h1 {
9+
color: #333;
10+
font-size: 2rem;
11+
}
12+
13+
p {
14+
color: #666;
15+
line-height: 1.6;
16+
}

test/unit/commandLine.test.ts

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import * as fs from 'node:fs';
2+
3+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4+
5+
vi.mock('node:fs', () => ({
6+
existsSync: vi.fn(() => true),
7+
statSync: vi.fn(() => ({ isDirectory: () => true }))
8+
}));
9+
10+
describe('commandLine', () => {
11+
const originalArgv = process.argv;
12+
const originalExit = process.exit;
13+
const originalConsoleLog = console.log;
14+
const originalConsoleError = console.error;
15+
16+
beforeEach(() => {
17+
vi.clearAllMocks();
18+
process.exit = vi.fn() as never;
19+
console.log = vi.fn();
20+
console.error = vi.fn();
21+
});
22+
23+
afterEach(() => {
24+
process.argv = originalArgv;
25+
process.exit = originalExit;
26+
console.log = originalConsoleLog;
27+
console.error = originalConsoleError;
28+
vi.resetModules();
29+
});
30+
31+
describe('argument parsing', () => {
32+
it('should parse arguments with --flag=value format', async () => {
33+
process.argv = [
34+
'node',
35+
'script.js',
36+
'--engine=async',
37+
'--sourcepath=/test/dist',
38+
'--outputfile=/test/output.h',
39+
'--etag=true',
40+
'--gzip=false'
41+
];
42+
43+
const { cmdLine } = await import('../../src/commandLine');
44+
45+
expect(cmdLine.engine).toBe('async');
46+
expect(cmdLine.sourcepath).toBe('/test/dist');
47+
expect(cmdLine.outputfile).toBe('/test/output.h');
48+
expect(cmdLine.etag).toBe('true');
49+
expect(cmdLine.gzip).toBe('false');
50+
});
51+
52+
it('should parse arguments with -flag value format', async () => {
53+
process.argv = ['node', 'script.js', '-e', 'psychic2', '-s', '/test/dist', '-o', '/test/output.h'];
54+
55+
const { cmdLine } = await import('../../src/commandLine');
56+
57+
expect(cmdLine.engine).toBe('psychic2');
58+
expect(cmdLine.sourcepath).toBe('/test/dist');
59+
expect(cmdLine.outputfile).toBe('/test/output.h');
60+
});
61+
62+
it('should parse arguments with --flag value format', async () => {
63+
process.argv = [
64+
'node',
65+
'script.js',
66+
'--engine',
67+
'espidf',
68+
'--sourcepath',
69+
'/test/dist',
70+
'--outputfile',
71+
'/test/output.h'
72+
];
73+
74+
const { cmdLine } = await import('../../src/commandLine');
75+
76+
expect(cmdLine.engine).toBe('espidf');
77+
expect(cmdLine.sourcepath).toBe('/test/dist');
78+
expect(cmdLine.outputfile).toBe('/test/output.h');
79+
});
80+
81+
it('should use default values when not specified', async () => {
82+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist'];
83+
84+
const { cmdLine } = await import('../../src/commandLine');
85+
86+
expect(cmdLine.engine).toBe('psychic');
87+
expect(cmdLine.outputfile).toBe('svelteesp32.h');
88+
expect(cmdLine.etag).toBe('false');
89+
expect(cmdLine.gzip).toBe('true');
90+
expect(cmdLine.created).toBe(false);
91+
expect(cmdLine.version).toBe('');
92+
expect(cmdLine.espmethod).toBe('initSvelteStaticFiles');
93+
expect(cmdLine.define).toBe('SVELTEESP32');
94+
expect(cmdLine.cachetime).toBe(0);
95+
});
96+
97+
it('should parse boolean flags', async () => {
98+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--created'];
99+
100+
const { cmdLine } = await import('../../src/commandLine');
101+
102+
expect(cmdLine.created).toBe(true);
103+
});
104+
105+
it('should parse version, espmethod, define, and cachetime', async () => {
106+
process.argv = [
107+
'node',
108+
'script.js',
109+
'--sourcepath=/test/dist',
110+
'--version=v1.0.0',
111+
'--espmethod=myMethod',
112+
'--define=MYPREFIX',
113+
'--cachetime=86400'
114+
];
115+
116+
const { cmdLine } = await import('../../src/commandLine');
117+
118+
expect(cmdLine.version).toBe('v1.0.0');
119+
expect(cmdLine.espmethod).toBe('myMethod');
120+
expect(cmdLine.define).toBe('MYPREFIX');
121+
expect(cmdLine.cachetime).toBe(86_400);
122+
});
123+
124+
it('should handle value with equals sign in --flag=value format', async () => {
125+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--version=v1.0.0=beta'];
126+
127+
const { cmdLine } = await import('../../src/commandLine');
128+
129+
expect(cmdLine.version).toBe('v1.0.0=beta');
130+
});
131+
});
132+
133+
describe('validation', () => {
134+
it('should validate engine values', async () => {
135+
process.argv = ['node', 'script.js', '--engine=invalid', '--sourcepath=/test/dist'];
136+
137+
await expect(import('../../src/commandLine')).rejects.toThrow('Invalid engine: invalid');
138+
});
139+
140+
it('should accept all valid engine values', async () => {
141+
for (const engine of ['psychic', 'psychic2', 'async', 'espidf']) {
142+
vi.resetModules();
143+
process.argv = ['node', 'script.js', `--engine=${engine}`, '--sourcepath=/test/dist'];
144+
145+
const { cmdLine } = await import('../../src/commandLine');
146+
expect(cmdLine.engine).toBe(engine);
147+
}
148+
});
149+
150+
it('should validate etag tri-state values', async () => {
151+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--etag=invalid'];
152+
153+
await expect(import('../../src/commandLine')).rejects.toThrow('Invalid etag: invalid');
154+
});
155+
156+
it('should accept all valid etag values', async () => {
157+
for (const etag of ['true', 'false', 'compiler']) {
158+
vi.resetModules();
159+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', `--etag=${etag}`];
160+
161+
const { cmdLine } = await import('../../src/commandLine');
162+
expect(cmdLine.etag).toBe(etag);
163+
}
164+
});
165+
166+
it('should validate gzip tri-state values', async () => {
167+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--gzip=invalid'];
168+
169+
await expect(import('../../src/commandLine')).rejects.toThrow('Invalid gzip: invalid');
170+
});
171+
172+
it('should validate cachetime is a number', async () => {
173+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--cachetime=notanumber'];
174+
175+
await expect(import('../../src/commandLine')).rejects.toThrow('Invalid cachetime: notanumber');
176+
});
177+
178+
it('should throw error for unknown flag', async () => {
179+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--unknown=value'];
180+
181+
await expect(import('../../src/commandLine')).rejects.toThrow('Unknown flag: --unknown');
182+
});
183+
184+
it('should throw error for missing value', async () => {
185+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--engine'];
186+
187+
await expect(import('../../src/commandLine')).rejects.toThrow('Missing value for flag: --engine');
188+
});
189+
190+
it('should throw error for invalid argument format', async () => {
191+
process.argv = ['node', 'script.js', '--sourcepath=/test/dist', '--='];
192+
193+
await expect(import('../../src/commandLine')).rejects.toThrow('Invalid argument format: --=');
194+
});
195+
});
196+
197+
describe('required arguments', () => {
198+
it('should exit when sourcepath is missing', async () => {
199+
process.argv = ['node', 'script.js'];
200+
201+
await import('../../src/commandLine').catch(() => {});
202+
203+
expect(console.error).toHaveBeenCalledWith('Error: --sourcepath is required');
204+
expect(process.exit).toHaveBeenCalledWith(0);
205+
});
206+
});
207+
208+
describe('directory validation', () => {
209+
it('should exit when source directory does not exist', async () => {
210+
process.argv = ['node', 'script.js', '--sourcepath=/nonexistent/path'];
211+
212+
const fsModule = await import('node:fs');
213+
vi.mocked(fsModule.existsSync).mockReturnValue(false);
214+
215+
await import('../../src/commandLine').catch(() => {});
216+
217+
expect(console.error).toHaveBeenCalledWith('Directory /nonexistent/path not exists or not a directory');
218+
expect(process.exit).toHaveBeenCalledWith(1);
219+
});
220+
221+
it('should exit when source path is not a directory', async () => {
222+
process.argv = ['node', 'script.js', '--sourcepath=/test/file.txt'];
223+
224+
const fsModule = await import('node:fs');
225+
vi.mocked(fsModule.existsSync).mockReturnValue(true);
226+
vi.mocked(fsModule.statSync).mockReturnValue({ isDirectory: () => false } as fs.Stats);
227+
228+
await import('../../src/commandLine').catch(() => {});
229+
230+
expect(console.error).toHaveBeenCalledWith('Directory /test/file.txt not exists or not a directory');
231+
expect(process.exit).toHaveBeenCalledWith(1);
232+
});
233+
});
234+
});

test/unit/consoleColor.test.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { greenLog, redLog, yellowLog } from '../../src/consoleColor';
4+
5+
describe('consoleColor', () => {
6+
describe('greenLog', () => {
7+
it('should wrap text with green ANSI codes', () => {
8+
const result = greenLog('success');
9+
expect(result).toBe('\u001B[32msuccess\u001B[0m');
10+
});
11+
12+
it('should handle empty strings', () => {
13+
const result = greenLog('');
14+
expect(result).toBe('\u001B[32m\u001B[0m');
15+
});
16+
17+
it('should handle strings with special characters', () => {
18+
const result = greenLog('Hello\nWorld!');
19+
expect(result).toBe('\u001B[32mHello\nWorld!\u001B[0m');
20+
});
21+
});
22+
23+
describe('yellowLog', () => {
24+
it('should wrap text with yellow ANSI codes', () => {
25+
const result = yellowLog('warning');
26+
expect(result).toBe('\u001B[33mwarning\u001B[0m');
27+
});
28+
29+
it('should handle empty strings', () => {
30+
const result = yellowLog('');
31+
expect(result).toBe('\u001B[33m\u001B[0m');
32+
});
33+
34+
it('should handle strings with special characters', () => {
35+
const result = yellowLog('Test@123');
36+
expect(result).toBe('\u001B[33mTest@123\u001B[0m');
37+
});
38+
});
39+
40+
describe('redLog', () => {
41+
it('should wrap text with red ANSI codes', () => {
42+
const result = redLog('error');
43+
expect(result).toBe('\u001B[31merror\u001B[0m');
44+
});
45+
46+
it('should handle empty strings', () => {
47+
const result = redLog('');
48+
expect(result).toBe('\u001B[31m\u001B[0m');
49+
});
50+
51+
it('should handle strings with numbers', () => {
52+
const result = redLog('Error 404');
53+
expect(result).toBe('\u001B[31mError 404\u001B[0m');
54+
});
55+
});
56+
57+
describe('all color functions', () => {
58+
it('should produce different color codes for each function', () => {
59+
const green = greenLog('test');
60+
const yellow = yellowLog('test');
61+
const red = redLog('test');
62+
63+
expect(green).not.toBe(yellow);
64+
expect(yellow).not.toBe(red);
65+
expect(red).not.toBe(green);
66+
});
67+
68+
it('should all end with reset code', () => {
69+
expect(greenLog('test')).toContain('\u001B[0m');
70+
expect(yellowLog('test')).toContain('\u001B[0m');
71+
expect(redLog('test')).toContain('\u001B[0m');
72+
});
73+
});
74+
});

0 commit comments

Comments
 (0)