Skip to content

Commit 70cad49

Browse files
authored
CI Unit Tests & other unit testing-related patches (#85)
2 parents d967f80 + 308f76c commit 70cad49

15 files changed

Lines changed: 333 additions & 92 deletions

File tree

.github/workflows/tests.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Test extension
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
- dev
8+
pull_request:
9+
branches:
10+
- master
11+
- dev
12+
workflow_dispatch: # in case we need to regenerate test coverage
13+
14+
jobs:
15+
test-desktop:
16+
name: Electron tests
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
include:
21+
- os: macos-latest
22+
name: macOS
23+
- os: windows-latest
24+
name: Windows
25+
- os: ubuntu-latest
26+
name: Linux
27+
runs-on: ${{ matrix.os }}
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
- name: Cache configs + modules
32+
uses: actions/cache@v4
33+
with:
34+
key: neuropilot-tests-${{ github.repository }}-${{ matrix.os }}
35+
path: |
36+
node_modules/
37+
.vscode-test/
38+
- name: Install Node.js
39+
uses: actions/setup-node@v4
40+
with:
41+
node-version: 22.x
42+
cache: 'npm'
43+
cache-dependency-path: './package-lock.json'
44+
- run: npm install
45+
- run: xvfb-run -a npm test
46+
if: runner.os == 'Linux'
47+
- run: npm test
48+
if: runner.os != 'Linux'
49+
# for now we'll stop with this
50+
# VSC-NeuroPilot/actions/send-test-repo-action will be added later
51+
#test-web:
52+
# name: Web tests
53+
# strategy:
54+
# fail-fast: false
55+
# matrix:
56+
# include:
57+
# - engine: webkit
58+
# browser: Safari
59+
# - engine: firefox
60+
# browser: Firefox
61+
# - engine: chromium
62+
# browser: Chrome
63+
# runs-on: ubuntu-latest

.vscode-test.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ export default defineConfig([
44
{
55
label: 'desktopUnitTest',
66
platform: 'desktop',
7-
files: 'out/test/**/*.test.js',
7+
files: 'out/desktop/test.js',
88
workspaceFolder: './test-playground',
99
browser: '',
1010
coverage: {
1111
include: ['src/**/*.ts'],
12-
exclude: ['src/test/**/*.test.ts', 'src/test/suite/index.ts'],
12+
exclude: ['src/test/**/*.test.ts', 'src/test/suite/desktop/index.ts', 'src/web/**/*'],
1313
output: './coverage',
1414
},
1515
env: {

.vscode/extensions.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"recommendations": ["astro-build.astro-vscode", "connor4312.esbuild-problem-matchers"],
2+
"recommendations": ["astro-build.astro-vscode", "connor4312.esbuild-problem-matchers", "ms-vscode.extension-test-runner"],
33
"unwantedRecommendations": []
44
}

.vscode/launch.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
"runtimeExecutable": "${execPath}",
4444
"args": [
4545
"--extensionDevelopmentPath=${workspaceFolder}",
46-
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index",
46+
"--extensionTestsPath=${workspaceFolder}/out/desktop/test.js",
4747
"${workspaceFolder}/test-playground"
4848
],
49-
"outFiles": ["${workspaceFolder}/out/test/**/*.js"],
49+
"outFiles": ["${workspaceFolder}/out/desktop/test.js"],
5050
"preLaunchTask": "watch:desktop"
5151
},
5252
{

esbuild-configs/desktop.esbuild.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export async function desktop(prodFlag, watchFlag) {
1414
outfile: 'out/desktop/extension.js',
1515
external: ['vscode'],
1616
logLevel: 'warning',
17+
tsconfig: './tsconfig.app.json',
1718
plugins: [
1819
/* add to the end of plugins array */
1920
esbuildProblemMatcherPlugin,
@@ -27,6 +28,40 @@ export async function desktop(prodFlag, watchFlag) {
2728
}
2829
}
2930

31+
export async function desktopTest(_prodFlag, watchFlag) {
32+
const ctx = await context({
33+
entryPoints: ['src/test/suite/desktop/index.ts'],
34+
bundle: true,
35+
format: 'cjs',
36+
minify: false, // Don't minify tests for better debugging
37+
sourcemap: true, // Always generate sourcemaps for tests
38+
sourcesContent: true, // Include source content for better debugging
39+
platform: 'node',
40+
outfile: 'out/desktop/test.js',
41+
tsconfig: './test-tsconfigs/tsconfig.app.json',
42+
external: [
43+
'vscode',
44+
'mocha',
45+
'@vscode/test-electron',
46+
],
47+
logLevel: 'warning',
48+
define: {
49+
// Define test environment variables
50+
'process.env.NODE_ENV': '"test"',
51+
},
52+
plugins: [
53+
esbuildProblemMatcherPlugin,
54+
],
55+
});
56+
57+
if (watchFlag) {
58+
await ctx.watch();
59+
} else {
60+
await ctx.rebuild();
61+
await ctx.dispose();
62+
}
63+
}
64+
3065
/**
3166
* @type {import('esbuild').Plugin}
3267
*/

esbuild-configs/web.esbuild.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export async function web(prodFlag, watchFlag) {
1515
outfile: 'out/web/extension.js',
1616
external: ['vscode'],
1717
logLevel: 'warning',
18+
tsconfig: './tsconfig.web.json',
1819
plugins: [
1920
polyfillNode({ polyfills: { // trying to make the build as small as possible
2021
child_process: false,
@@ -40,6 +41,52 @@ export async function web(prodFlag, watchFlag) {
4041
}
4142
}
4243

44+
export async function webTest(_prodFlag, watchFlag) {
45+
const ctx = await context({
46+
entryPoints: ['src/test/suite/web/index.ts'],
47+
bundle: true,
48+
format: 'cjs',
49+
minify: false, // Don't minify tests for better debugging
50+
sourcemap: true, // Always generate sourcemaps for tests
51+
sourcesContent: true, // Include source content for better debugging
52+
platform: 'browser',
53+
outfile: 'out/web/test.js',
54+
tsconfig: './test-tsconfigs/tsconfig.web.json',
55+
external: [
56+
'vscode',
57+
'mocha',
58+
'@vscode/test-web',
59+
],
60+
logLevel: 'warning',
61+
define: {
62+
// Define test environment variables
63+
'process.env.NODE_ENV': '"test"',
64+
},
65+
plugins: [
66+
polyfillNode({ polyfills: { // trying to make the build as small as possible
67+
child_process: false,
68+
module: false,
69+
os: false,
70+
path: false,
71+
punycode: false,
72+
stream: false,
73+
sys: false,
74+
v8: false,
75+
vm: false,
76+
zlib: false,
77+
}}),
78+
esbuildProblemMatcherPlugin,
79+
],
80+
});
81+
82+
if (watchFlag) {
83+
await ctx.watch();
84+
} else {
85+
await ctx.rebuild();
86+
await ctx.dispose();
87+
}
88+
}
89+
4390
/**
4491
* @type {import('esbuild').Plugin}
4592
*/

esbuild.mjs

Lines changed: 81 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { web } from './esbuild-configs/web.esbuild.js';
2-
import { desktop } from './esbuild-configs/desktop.esbuild.js';
1+
import { web, webTest } from './esbuild-configs/web.esbuild.js';
2+
import { desktop, desktopTest } from './esbuild-configs/desktop.esbuild.js';
33
import * as fs from 'fs';
44
import chalk from 'chalk';
55

@@ -44,6 +44,7 @@ function determineProductionMode() {
4444
const production = determineProductionMode();
4545
const watch = process.argv.includes('--watch');
4646
const modeArgIndex = process.argv.indexOf('--mode');
47+
const test = process.argv.includes('--test');
4748
const mode = modeArgIndex !== -1 && process.argv[modeArgIndex + 1] ? process.argv[modeArgIndex + 1] : 'default';
4849

4950
// Log the build configuration
@@ -53,15 +54,29 @@ if (process.env.NODE_ENV) {
5354
}
5455

5556
let outDir;
56-
switch (mode.toLowerCase()) {
57-
case 'web':
58-
outDir = './out/web';
59-
break;
60-
case 'desktop':
61-
outDir = './out/desktop';
62-
break;
63-
default:
64-
outDir = './out';
57+
if (test) {
58+
switch (mode.toLowerCase()) {
59+
case 'web':
60+
outDir = ['./out/web/test.js'];
61+
break;
62+
case 'desktop':
63+
outDir = ['./out/desktop/test.js'];
64+
break;
65+
default:
66+
outDir = ['./out/desktop/test.js', './out/web/test.js'];
67+
break;
68+
}
69+
} else {
70+
switch (mode.toLowerCase()) {
71+
case 'web':
72+
outDir = ['./out/web/extension.js'];
73+
break;
74+
case 'desktop':
75+
outDir = ['./out/desktop/extension.js'];
76+
break;
77+
default:
78+
outDir = ['./out/desktop/extension.js', './out/web/extension.js'];
79+
}
6580
}
6681
if (fs.existsSync(outDir)) {
6782
console.log(chalk.yellow(`🗑️ Output directory ${outDir} already exists, removing dir...`));
@@ -73,38 +88,70 @@ if (fs.existsSync(outDir)) {
7388
try {
7489
switch (mode.toLowerCase()) {
7590
case 'web':
76-
console.log(chalk.blue(`🌐 ${watch ? 'Watching' : 'Running'} web build...`));
77-
await web(production, watch).catch(erm => {
78-
console.error(chalk.red.bold(`💥 Web build failed: ${erm}`));
79-
process.exit(1);
80-
});
81-
console.log(chalk.green.bold.underline('🧰 Web build completed successfully!'));
91+
if (test) {
92+
console.log(chalk.blue(`🌐 ${watch ? 'Watching' : 'Running'} web test build...`));
93+
await webTest(production, watch).catch(erm => {
94+
console.error(chalk.red.bold(`💥 Web test build failed: ${erm}`));
95+
process.exit(1);
96+
});
97+
console.log(chalk.green.bold.underline('🧪 Web tests compiled successfully!'));
98+
} else {
99+
console.log(chalk.blue(`🌐 ${watch ? 'Watching' : 'Running'} web build...`));
100+
await web(production, watch).catch(erm => {
101+
console.error(chalk.red.bold(`💥 Web build failed: ${erm}`));
102+
process.exit(1);
103+
});
104+
console.log(chalk.green.bold.underline('🧰 Web build completed successfully!'));
105+
}
82106
break;
83107
case 'desktop':
84-
console.log(chalk.blue(`🖥️ ${watch ? 'Watching' : 'Running'} desktop build...`));
85-
await desktop(production, watch).catch(erm => {
86-
console.error(chalk.red.bold(`💥 Desktop build failed: ${erm}`));
87-
process.exit(1);
88-
});
89-
console.log(chalk.green.bold.underline('🧰 Desktop build completed successfully!'));
108+
if (test) {
109+
console.log(chalk.blue(`🖥️ ${watch ? 'Watching' : 'Running'} desktop test build...`));
110+
await desktopTest(production, watch).catch(erm => {
111+
console.error(chalk.red.bold(`💥 Desktop test build failed: ${erm}`));
112+
process.exit(1);
113+
});
114+
console.log(chalk.green.bold.underline('🧪 Desktop tests compiled successfully!'));
115+
} else {
116+
console.log(chalk.blue(`🖥️ ${watch ? 'Watching' : 'Running'} desktop build...`));
117+
await desktop(production, watch).catch(erm => {
118+
console.error(chalk.red.bold(`💥 Desktop build failed: ${erm}`));
119+
process.exit(1);
120+
});
121+
console.log(chalk.green.bold.underline('🧰 Desktop build completed successfully!'));
122+
}
90123
break;
91124
case 'default':
92125
// Can't use watch while building both.
93126
if (watch) {
94127
console.error(chalk.yellow.bold('⚠️ Cannot use flag --watch while building both desktop and web'));
95128
//process.exit(1); we'll just continue building it normally ig
96129
}
97-
console.log(chalk.blue('🖥️ Running desktop build...'));
98-
await desktop(production, false).catch(erm => {
99-
console.error(chalk.red.bold(`💥 Desktop build failed: ${erm}`));
100-
process.exit(1);
101-
});
102-
console.log(chalk.blue('🌐 Running web build...'));
103-
await web(production, false).catch(erm => {
104-
console.error(chalk.red.bold(`💥 Web build failed: ${erm}`));
105-
process.exit(1);
106-
});
107-
console.log(chalk.green.bold.underline('🎉 Builds completed successfully!'));
130+
if (test) {
131+
console.log(chalk.blue('🖥️🧪 Running desktop test build...'));
132+
await desktopTest(production, false).catch(erm => {
133+
console.error(chalk.red.bold(`💥 Desktop test build failed: ${erm}`));
134+
process.exit(1);
135+
});
136+
console.log(chalk.blue('🌐🧪 Running web test build...'));
137+
await webTest(production, false).catch(erm => {
138+
console.error(chalk.red.bold(`💥 Web test build failed: ${erm}`));
139+
process.exit(1);
140+
});
141+
console.log(chalk.green.bold.underline('🎉🧪 Tests compiled successfully!'));
142+
} else {
143+
console.log(chalk.blue('🖥️ Running desktop build...'));
144+
await desktop(production, false).catch(erm => {
145+
console.error(chalk.red.bold(`💥 Desktop build failed: ${erm}`));
146+
process.exit(1);
147+
});
148+
console.log(chalk.blue('🌐 Running web build...'));
149+
await web(production, false).catch(erm => {
150+
console.error(chalk.red.bold(`💥 Web build failed: ${erm}`));
151+
process.exit(1);
152+
});
153+
console.log(chalk.green.bold.underline('🎉 Builds completed successfully!'));
154+
}
108155
break;
109156
default:
110157
console.error(chalk.red.bold(`❌ Unknown mode: ${mode}`));

package-lock.json

Lines changed: 0 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)