Skip to content

Commit a3ddb70

Browse files
committed
chore: add Windows to the unit tests CI
1 parent b3f03f9 commit a3ddb70

File tree

8 files changed

+114
-68
lines changed

8 files changed

+114
-68
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,13 @@ jobs:
592592
test-unit:
593593
name: Unit Tests
594594
if: always() && needs.changes.outputs.build-unit == 'true'
595-
runs-on: ubuntu-latest
595+
strategy:
596+
matrix:
597+
settings:
598+
- host: ubuntu-latest
599+
- host: windows-latest
600+
601+
runs-on: ${{ matrix.settings.host }}
596602
needs:
597603
- changes
598604
- build-other-packages

packages/insights/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"@types/density-clustering": "1.3.3",
2323
"@types/node": "24.0.4",
2424
"autoprefixer": "10.4.19",
25-
"better-sqlite3": "9.6.0",
25+
"better-sqlite3": "12.2.0",
2626
"eslint": "9.25.1",
2727
"eslint-plugin-qwik": "workspace:*",
2828
"globals": "16.0.0",

packages/qwik/src/cli/add/update-files.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import fs from 'node:fs';
2-
import { extname, join, normalize } from 'node:path';
2+
import { extname, join } from 'node:path';
33
import type { FsUpdates, UpdateAppOptions } from '../types';
44
import { getPackageManager } from '../utils/utils';
55

@@ -22,18 +22,12 @@ export async function mergeIntegrationDir(
2222
const s = await fs.promises.stat(srcChildPath);
2323

2424
if (s.isDirectory()) {
25-
await mergeIntegrationDir(
26-
fileUpdates,
27-
opts,
28-
srcChildPath,
29-
normalize(destRootPath).replace(/\\/g, '/'),
30-
alwaysInRoot
31-
);
25+
await mergeIntegrationDir(fileUpdates, opts, srcChildPath, destRootPath, alwaysInRoot);
3226
} else if (s.isFile()) {
3327
const finalDestPath = getFinalDestPath(opts, destRootPath, destDir, destName, alwaysInRoot);
3428

3529
if (destName === 'package.json') {
36-
await mergePackageJsons(fileUpdates, srcChildPath, destRootPath.replace(/\\/g, '/'));
30+
await mergePackageJsons(fileUpdates, srcChildPath, destRootPath);
3731
} else if (destName === 'settings.json') {
3832
await mergeJsons(fileUpdates, srcChildPath, finalDestPath);
3933
} else if (destName === 'README.md') {
@@ -43,7 +37,7 @@ export async function mergeIntegrationDir(
4337
destName === '.prettierignore' ||
4438
destName === '.eslintignore'
4539
) {
46-
await mergeIgnoresFile(fileUpdates, srcChildPath, destRootPath.replace(/\\/g, '/'));
40+
await mergeIgnoresFile(fileUpdates, srcChildPath, destRootPath);
4741
} else if (ext === '.css') {
4842
await mergeCss(fileUpdates, srcChildPath, finalDestPath, opts);
4943
} else if (fs.existsSync(finalDestPath)) {
@@ -85,8 +79,7 @@ function getFinalDestPath(
8579
? destRootPath
8680
: destChildPath;
8781

88-
// Normalize path separators to forward slashes for cross-platform compatibility
89-
return normalize(finalDestPath).replace(/\\/g, '/');
82+
return finalDestPath;
9083
}
9184

9285
async function mergePackageJsons(fileUpdates: FsUpdates, srcPath: string, destPath: string) {

packages/qwik/src/cli/add/update-files.unit.ts

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
11
import { fs } from 'memfs';
22
import { join } from 'path';
3-
import { describe, expect, test, vi } from 'vitest';
3+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
4+
import { normalizePath } from '../../testing/util';
45
import type { FsUpdates, UpdateAppOptions } from '../types';
56
import { mergeIntegrationDir } from './update-files';
67

78
vi.mock('node:fs', () => ({
89
default: fs,
910
}));
1011

11-
function setup() {
12-
const fakeSrcDir = 'srcDir/subSrcDir';
12+
let fakeSrcDir: string;
13+
let fakeDestDir: string;
14+
let fakeFileUpdates: FsUpdates;
15+
let fakeOpts: UpdateAppOptions;
16+
17+
beforeEach(() => {
18+
// Reset the mock filesystem before each test
19+
fs.mkdirSync(join('srcDir', 'subSrcDir'), { recursive: true });
20+
fs.mkdirSync(join('destDir', 'subDestDir'), { recursive: true });
21+
22+
fakeSrcDir = join('srcDir', 'subSrcDir');
1323
createFakeFiles(fakeSrcDir);
1424

15-
const fakeDestDir = 'destDir/subDestDir';
25+
fakeDestDir = join('destDir', 'subDestDir');
1626

17-
const fakeFileUpdates: FsUpdates = {
27+
fakeFileUpdates = {
1828
files: [],
1929
installedDeps: {},
2030
installedScripts: [],
2131
};
2232

23-
const fakeOpts: UpdateAppOptions = {
33+
fakeOpts = {
2434
rootDir: fakeDestDir,
2535
integration: 'integration',
2636
};
37+
});
2738

28-
return {
29-
fakeSrcDir,
30-
fakeDestDir,
31-
fakeFileUpdates,
32-
fakeOpts,
33-
};
34-
}
39+
afterEach(() => {
40+
vi.clearAllMocks();
41+
// Clean up the mock filesystem
42+
fs.rmSync(join('srcDir'), { recursive: true, force: true });
43+
fs.rmSync(join('destDir'), { recursive: true, force: true });
44+
});
3545

3646
function createFakeFiles(dir: string) {
3747
// Create fake src files
@@ -43,23 +53,19 @@ function createFakeFiles(dir: string) {
4353

4454
describe('mergeIntegrationDir', () => {
4555
test('should merge integration directory', async () => {
46-
const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup();
47-
4856
await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir);
4957

50-
const actualResults = fakeFileUpdates.files.map((f) => f.path);
58+
const actualResults = fakeFileUpdates.files.map((f) => normalizePath(f.path));
5159
const expectedResults = [
52-
'destDir/subDestDir/fake.ts',
53-
'destDir/subDestDir/package.json',
54-
'destDir/subDestDir/src/global.css',
60+
normalizePath(join('destDir', 'subDestDir', 'fake.ts')),
61+
normalizePath(join('destDir', 'subDestDir', 'package.json')),
62+
normalizePath(join('destDir', 'subDestDir', 'src', 'global.css')),
5563
];
5664

5765
expect(actualResults).toEqual(expectedResults);
5866
});
5967

6068
test('should merge integration directory in a monorepo', async () => {
61-
const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup();
62-
6369
// Create a global file in the destination director
6470
const monorepoSubDir = join(fakeDestDir, 'apps', 'subpackage', 'src');
6571
fs.mkdirSync(monorepoSubDir, { recursive: true });
@@ -72,25 +78,27 @@ describe('mergeIntegrationDir', () => {
7278
fs.mkdirSync(join(fakeSrcDir, 'should-stay'), { recursive: true });
7379
fs.writeFileSync(join(fakeSrcDir, 'should-stay', 'should-also-stay.ts'), 'fake file');
7480

75-
fakeOpts.projectDir = 'apps/subpackage';
81+
fakeOpts.projectDir = join('apps', 'subpackage');
7682
fakeOpts.installDeps = true;
7783
const fakeAlwaysInRoot = ['should-stay-in-root.ts', 'should-stay'];
7884

7985
await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir, fakeAlwaysInRoot);
8086

81-
const actualResults = fakeFileUpdates.files.map((f) => f.path);
87+
const actualResults = fakeFileUpdates.files.map((f) => normalizePath(f.path));
8288
const expectedResults = [
83-
`destDir/subDestDir/apps/subpackage/fake.ts`,
84-
`destDir/subDestDir/should-stay-in-root.ts`,
85-
`destDir/subDestDir/package.json`,
86-
`destDir/subDestDir/should-stay/should-also-stay.ts`,
87-
`destDir/subDestDir/apps/subpackage/src/global.css`,
89+
normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'fake.ts')),
90+
normalizePath(join('destDir', 'subDestDir', 'should-stay-in-root.ts')),
91+
normalizePath(join('destDir', 'subDestDir', 'package.json')),
92+
normalizePath(join('destDir', 'subDestDir', 'should-stay', 'should-also-stay.ts')),
93+
normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'src', 'global.css')),
8894
];
8995

9096
expect(actualResults).toEqual(expectedResults);
9197

9298
const actualGlobalCssContent = fakeFileUpdates.files.find(
93-
(f) => f.path === `destDir/subDestDir/apps/subpackage/src/global.css`
99+
(f) =>
100+
normalizePath(f.path) ===
101+
normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'src', 'global.css'))
94102
)?.content;
95103

96104
expect(actualGlobalCssContent).toBe('p{color: red}\n\n/* CSS */\n');

packages/qwik/src/optimizer/src/plugins/plugin.unit.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ test('defaults', async () => {
2222
assert.deepEqual(opts.debug, false);
2323
assert.deepEqual(opts.rootDir, normalizePath(cwd));
2424
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']);
25-
assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
25+
assert.deepEqual((opts.input as string[]).map(normalizePath), [
26+
normalizePath(resolve(cwd, 'src', 'root')),
27+
]);
2628
assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'dist')));
2729
assert.deepEqual(opts.manifestInput, null);
2830
assert.deepEqual(opts.manifestOutput, null);
@@ -39,7 +41,9 @@ test('defaults (buildMode: production)', async () => {
3941
assert.deepEqual(opts.debug, false);
4042
assert.deepEqual(opts.rootDir, normalizePath(cwd));
4143
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']);
42-
assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
44+
assert.deepEqual((opts.input as string[]).map(normalizePath), [
45+
normalizePath(resolve(cwd, 'src', 'root')),
46+
]);
4347
assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'dist')));
4448
assert.deepEqual(opts.manifestInput, null);
4549
assert.deepEqual(opts.manifestOutput, null);
@@ -57,7 +61,9 @@ test('defaults (target: ssr)', async () => {
5761
assert.deepEqual(opts.debug, false);
5862
assert.deepEqual(opts.rootDir, normalizePath(cwd));
5963
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']);
60-
assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]);
64+
assert.deepEqual((opts.input as string[]).map(normalizePath), [
65+
normalizePath(resolve(cwd, 'src', 'entry.ssr')),
66+
]);
6167
assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'server')));
6268
assert.deepEqual(opts.manifestInput, null);
6369
assert.deepEqual(opts.manifestOutput, null);
@@ -74,7 +80,9 @@ test('defaults (buildMode: production, target: ssr)', async () => {
7480
assert.deepEqual(opts.debug, false);
7581
assert.deepEqual(opts.rootDir, normalizePath(cwd));
7682
assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']);
77-
assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]);
83+
assert.deepEqual((opts.input as string[]).map(normalizePath), [
84+
normalizePath(resolve(cwd, 'src', 'entry.ssr')),
85+
]);
7886
assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'server')));
7987
assert.deepEqual(opts.manifestInput, null);
8088
assert.deepEqual(opts.manifestOutput, null);

packages/qwik/src/optimizer/src/plugins/rollup.unit.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ test('rollup default input options, client', async () => {
3030
const rollupInputOpts: Rollup.InputOptions = await plugin.options!({});
3131

3232
assert.deepEqual(typeof rollupInputOpts.onwarn, 'function');
33-
assert.deepEqual(rollupInputOpts.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
33+
assert.deepEqual((rollupInputOpts.input as string[]).map(normalizePath), [
34+
normalizePath(resolve(cwd, 'src', 'root')),
35+
]);
3436
});
3537

3638
test('rollup default input options, ssr', async () => {
@@ -44,8 +46,12 @@ test('rollup default input options, ssr', async () => {
4446

4547
assert.deepEqual(typeof rollupInputOpts.onwarn, 'function');
4648
assert.deepEqual(rollupInputOpts.treeshake, undefined);
47-
assert.deepEqual(rollupInputOpts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]);
48-
assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]);
49+
assert.deepEqual((rollupInputOpts.input as string[]).map(normalizePath), [
50+
normalizePath(resolve(cwd, 'src', 'entry.ssr')),
51+
]);
52+
assert.deepEqual((opts.input as string[]).map(normalizePath), [
53+
normalizePath(resolve(cwd, 'src', 'entry.ssr')),
54+
]);
4955
});
5056

5157
test('rollup default set input options, ssr', async () => {

packages/qwik/src/optimizer/src/plugins/vite.unit.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,14 @@ test('command: serve, mode: development', async () => {
104104
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
105105
assert.deepEqual(chunkFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`);
106106
assert.deepEqual(entryFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`);
107-
assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js');
108-
assert.deepEqual(entryFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js');
107+
const relDev = path.relative(cwd, chunkInfoMocks[1].name);
108+
const sanitizedDev = relDev
109+
.replace(/^\(\.\.\/\)+/, '')
110+
.replace(/^\/+/, '')
111+
.replace(/\//g, '-');
112+
const expectedDevChunk = `build/${sanitizedDev}.js`;
113+
assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), expectedDevChunk);
114+
assert.deepEqual(entryFileNames(chunkInfoMocks[1]), expectedDevChunk);
109115
assert.deepEqual(outputOptions.format, 'es');
110116

111117
assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
@@ -188,13 +194,21 @@ test('command: build, mode: development', async () => {
188194
assert.deepEqual(plugin.enforce, 'pre');
189195
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
190196
assert.deepEqual(build.emptyOutDir, undefined);
191-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
197+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
198+
normalizePath(resolve(cwd, 'src', 'root')),
199+
]);
192200

193201
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
194202
assert.deepEqual(chunkFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`);
195203
assert.deepEqual(entryFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`);
196-
assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js');
197-
assert.deepEqual(entryFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js');
204+
const relBuildDev = path.relative(cwd, chunkInfoMocks[1].name);
205+
const sanitizedBuildDev = relBuildDev
206+
.replace(/^\(\.\.\/\)+/, '')
207+
.replace(/^\/+/, '')
208+
.replace(/\//g, '-');
209+
const expectedBuildDevChunk = `build/${sanitizedBuildDev}.js`;
210+
assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), expectedBuildDevChunk);
211+
assert.deepEqual(entryFileNames(chunkInfoMocks[1]), expectedBuildDevChunk);
198212

199213
assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]);
200214
assert.deepEqual(build.ssr, undefined);
@@ -233,7 +247,9 @@ test('command: build, mode: production', async () => {
233247
assert.deepEqual(plugin.enforce, 'pre');
234248
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist')));
235249
assert.deepEqual(build.emptyOutDir, undefined);
236-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
250+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
251+
normalizePath(resolve(cwd, 'src', 'root')),
252+
]);
237253

238254
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
239255
assert.deepEqual(outputOptions.chunkFileNames, 'build/q-[hash].js');
@@ -275,7 +291,9 @@ test('command: build, --mode production (client)', async () => {
275291

276292
assert.deepEqual(opts.target, 'client');
277293
assert.deepEqual(opts.buildMode, 'production');
278-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]);
294+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
295+
normalizePath(resolve(cwd, 'src', 'root')),
296+
]);
279297
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'client-dist')));
280298
assert.deepEqual(build.emptyOutDir, undefined);
281299
});
@@ -304,7 +322,9 @@ test('command: build, --ssr entry.server.tsx', async () => {
304322
assert.deepEqual(plugin.enforce, 'pre');
305323
assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'server')));
306324
assert.deepEqual(build.emptyOutDir, undefined);
307-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'entry.server.tsx'))]);
325+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
326+
normalizePath(resolve(cwd, 'src', 'entry.server.tsx')),
327+
]);
308328

309329
assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]');
310330
assert.isFunction(outputOptions.chunkFileNames);
@@ -345,7 +365,9 @@ test('command: serve, --mode ssr', async () => {
345365
assert.deepEqual(opts.buildMode, 'development');
346366
assert.deepEqual(build.minify, undefined);
347367
assert.deepEqual(build.ssr, undefined);
348-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'renderz.tsx'))]);
368+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
369+
normalizePath(resolve(cwd, 'src', 'renderz.tsx')),
370+
]);
349371
assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'ssr-dist')));
350372
assert.deepEqual(build.emptyOutDir, undefined);
351373
assert.deepEqual(c.publicDir, undefined);
@@ -374,7 +396,9 @@ test('command: serve, --mode ssr with build.assetsDir', async () => {
374396
assert.deepEqual(opts.buildMode, 'development');
375397
assert.deepEqual(build.minify, undefined);
376398
assert.deepEqual(build.ssr, undefined);
377-
assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'renderz.tsx'))]);
399+
assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [
400+
normalizePath(resolve(cwd, 'src', 'renderz.tsx')),
401+
]);
378402
assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'ssr-dist')));
379403
assert.deepEqual(build.emptyOutDir, undefined);
380404
assert.deepEqual(c.publicDir, undefined);

0 commit comments

Comments
 (0)