diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6dd9ff2e82..0d46cba5197 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -592,7 +592,13 @@ jobs: test-unit: name: Unit Tests if: always() && needs.changes.outputs.build-unit == 'true' - runs-on: ubuntu-latest + strategy: + matrix: + settings: + - host: ubuntu-latest + - host: windows-latest + + runs-on: ${{ matrix.settings.host }} needs: - changes - build-other-packages diff --git a/packages/qwik/src/cli/add/update-files.unit.ts b/packages/qwik/src/cli/add/update-files.unit.ts index 47b9b4c8f9b..b5441066406 100644 --- a/packages/qwik/src/cli/add/update-files.unit.ts +++ b/packages/qwik/src/cli/add/update-files.unit.ts @@ -1,6 +1,7 @@ import { fs } from 'memfs'; import { join } from 'path'; -import { describe, expect, test, vi } from 'vitest'; +import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'; +import { normalizePath } from '../../testing/util'; import type { FsUpdates, UpdateAppOptions } from '../types'; import { mergeIntegrationDir } from './update-files'; @@ -8,30 +9,39 @@ vi.mock('node:fs', () => ({ default: fs, })); -function setup() { - const fakeSrcDir = 'srcDir/subSrcDir'; +let fakeSrcDir: string; +let fakeDestDir: string; +let fakeFileUpdates: FsUpdates; +let fakeOpts: UpdateAppOptions; + +beforeEach(() => { + // Reset the mock filesystem before each test + fs.mkdirSync(join('srcDir', 'subSrcDir'), { recursive: true }); + fs.mkdirSync(join('destDir', 'subDestDir'), { recursive: true }); + + fakeSrcDir = join('srcDir', 'subSrcDir'); createFakeFiles(fakeSrcDir); - const fakeDestDir = 'destDir/subDestDir'; + fakeDestDir = join('destDir', 'subDestDir'); - const fakeFileUpdates: FsUpdates = { + fakeFileUpdates = { files: [], installedDeps: {}, installedScripts: [], }; - const fakeOpts: UpdateAppOptions = { + fakeOpts = { rootDir: fakeDestDir, integration: 'integration', }; +}); - return { - fakeSrcDir, - fakeDestDir, - fakeFileUpdates, - fakeOpts, - }; -} +afterEach(() => { + vi.clearAllMocks(); + // Clean up the mock filesystem + fs.rmSync(join('srcDir'), { recursive: true, force: true }); + fs.rmSync(join('destDir'), { recursive: true, force: true }); +}); function createFakeFiles(dir: string) { // Create fake src files @@ -43,23 +53,19 @@ function createFakeFiles(dir: string) { describe('mergeIntegrationDir', () => { test('should merge integration directory', async () => { - const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup(); - await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir); - const actualResults = fakeFileUpdates.files.map((f) => f.path); + const actualResults = fakeFileUpdates.files.map((f) => normalizePath(f.path)); const expectedResults = [ - 'destDir/subDestDir/fake.ts', - 'destDir/subDestDir/package.json', - 'destDir/subDestDir/src/global.css', + normalizePath(join('destDir', 'subDestDir', 'fake.ts')), + normalizePath(join('destDir', 'subDestDir', 'package.json')), + normalizePath(join('destDir', 'subDestDir', 'src', 'global.css')), ]; expect(actualResults).toEqual(expectedResults); }); test('should merge integration directory in a monorepo', async () => { - const { fakeSrcDir, fakeDestDir, fakeFileUpdates, fakeOpts } = setup(); - // Create a global file in the destination director const monorepoSubDir = join(fakeDestDir, 'apps', 'subpackage', 'src'); fs.mkdirSync(monorepoSubDir, { recursive: true }); @@ -72,25 +78,27 @@ describe('mergeIntegrationDir', () => { fs.mkdirSync(join(fakeSrcDir, 'should-stay'), { recursive: true }); fs.writeFileSync(join(fakeSrcDir, 'should-stay', 'should-also-stay.ts'), 'fake file'); - fakeOpts.projectDir = 'apps/subpackage'; + fakeOpts.projectDir = join('apps', 'subpackage'); fakeOpts.installDeps = true; const fakeAlwaysInRoot = ['should-stay-in-root.ts', 'should-stay']; await mergeIntegrationDir(fakeFileUpdates, fakeOpts, fakeSrcDir, fakeDestDir, fakeAlwaysInRoot); - const actualResults = fakeFileUpdates.files.map((f) => f.path); + const actualResults = fakeFileUpdates.files.map((f) => normalizePath(f.path)); const expectedResults = [ - `destDir/subDestDir/apps/subpackage/fake.ts`, - `destDir/subDestDir/should-stay-in-root.ts`, - `destDir/subDestDir/package.json`, - `destDir/subDestDir/should-stay/should-also-stay.ts`, - `destDir/subDestDir/apps/subpackage/src/global.css`, + normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'fake.ts')), + normalizePath(join('destDir', 'subDestDir', 'should-stay-in-root.ts')), + normalizePath(join('destDir', 'subDestDir', 'package.json')), + normalizePath(join('destDir', 'subDestDir', 'should-stay', 'should-also-stay.ts')), + normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'src', 'global.css')), ]; expect(actualResults).toEqual(expectedResults); const actualGlobalCssContent = fakeFileUpdates.files.find( - (f) => f.path === `destDir/subDestDir/apps/subpackage/src/global.css` + (f) => + normalizePath(f.path) === + normalizePath(join('destDir', 'subDestDir', 'apps', 'subpackage', 'src', 'global.css')) )?.content; expect(actualGlobalCssContent).toBe('p{color: red}\n\n/* CSS */\n'); diff --git a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts index d37a262c1cf..32b8fe8de2c 100644 --- a/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts +++ b/packages/qwik/src/optimizer/src/plugins/plugin.unit.ts @@ -22,7 +22,9 @@ test('defaults', async () => { assert.deepEqual(opts.debug, false); assert.deepEqual(opts.rootDir, normalizePath(cwd)); assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']); - assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((opts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'dist'))); assert.deepEqual(opts.manifestInput, null); assert.deepEqual(opts.manifestOutput, null); @@ -39,7 +41,9 @@ test('defaults (buildMode: production)', async () => { assert.deepEqual(opts.debug, false); assert.deepEqual(opts.rootDir, normalizePath(cwd)); assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']); - assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((opts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'dist'))); assert.deepEqual(opts.manifestInput, null); assert.deepEqual(opts.manifestOutput, null); @@ -57,7 +61,9 @@ test('defaults (target: ssr)', async () => { assert.deepEqual(opts.debug, false); assert.deepEqual(opts.rootDir, normalizePath(cwd)); assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']); - assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]); + assert.deepEqual((opts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'entry.ssr')), + ]); assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'server'))); assert.deepEqual(opts.manifestInput, null); assert.deepEqual(opts.manifestOutput, null); @@ -74,7 +80,9 @@ test('defaults (buildMode: production, target: ssr)', async () => { assert.deepEqual(opts.debug, false); assert.deepEqual(opts.rootDir, normalizePath(cwd)); assert.deepEqual(opts.tsconfigFileNames, ['./tsconfig.json']); - assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]); + assert.deepEqual((opts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'entry.ssr')), + ]); assert.deepEqual(opts.outDir, normalizePath(resolve(cwd, 'server'))); assert.deepEqual(opts.manifestInput, null); assert.deepEqual(opts.manifestOutput, null); diff --git a/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts b/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts index 01a94687fa4..9288a8a1663 100644 --- a/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts +++ b/packages/qwik/src/optimizer/src/plugins/rollup.unit.ts @@ -30,7 +30,9 @@ test('rollup default input options, client', async () => { const rollupInputOpts: Rollup.InputOptions = await plugin.options!({}); assert.deepEqual(typeof rollupInputOpts.onwarn, 'function'); - assert.deepEqual(rollupInputOpts.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((rollupInputOpts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); }); test('rollup default input options, ssr', async () => { @@ -44,8 +46,12 @@ test('rollup default input options, ssr', async () => { assert.deepEqual(typeof rollupInputOpts.onwarn, 'function'); assert.deepEqual(rollupInputOpts.treeshake, undefined); - assert.deepEqual(rollupInputOpts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]); - assert.deepEqual(opts.input, [normalizePath(resolve(cwd, 'src', 'entry.ssr'))]); + assert.deepEqual((rollupInputOpts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'entry.ssr')), + ]); + assert.deepEqual((opts.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'entry.ssr')), + ]); }); test('rollup default set input options, ssr', async () => { diff --git a/packages/qwik/src/optimizer/src/plugins/vite.unit.ts b/packages/qwik/src/optimizer/src/plugins/vite.unit.ts index 2730bfb0471..7526318d77e 100644 --- a/packages/qwik/src/optimizer/src/plugins/vite.unit.ts +++ b/packages/qwik/src/optimizer/src/plugins/vite.unit.ts @@ -96,8 +96,14 @@ test('command: serve, mode: development', async () => { assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]'); assert.deepEqual(chunkFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`); assert.deepEqual(entryFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`); - assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js'); - assert.deepEqual(entryFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js'); + const relDev = path.relative(cwd, chunkInfoMocks[1].name); + const sanitizedDev = relDev + .replace(/^\(\.\.\/\)+/, '') + .replace(/^\/+/, '') + .replace(/\//g, '-'); + const expectedDevChunk = `build/${sanitizedDev}.js`; + assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), expectedDevChunk); + assert.deepEqual(entryFileNames(chunkInfoMocks[1]), expectedDevChunk); assert.deepEqual(outputOptions.format, 'es'); assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]); @@ -180,13 +186,21 @@ test('command: build, mode: development', async () => { assert.deepEqual(plugin.enforce, 'pre'); assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist'))); assert.deepEqual(build.emptyOutDir, undefined); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]'); assert.deepEqual(chunkFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`); assert.deepEqual(entryFileNames(chunkInfoMocks[0]), `build/chunk.tsx.js`); - assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js'); - assert.deepEqual(entryFileNames(chunkInfoMocks[1]), 'build/app-chunk.tsx.js'); + const relBuildDev = path.relative(cwd, chunkInfoMocks[1].name); + const sanitizedBuildDev = relBuildDev + .replace(/^\(\.\.\/\)+/, '') + .replace(/^\/+/, '') + .replace(/\//g, '-'); + const expectedBuildDevChunk = `build/${sanitizedBuildDev}.js`; + assert.deepEqual(chunkFileNames(chunkInfoMocks[1]), expectedBuildDevChunk); + assert.deepEqual(entryFileNames(chunkInfoMocks[1]), expectedBuildDevChunk); assert.deepEqual(build.dynamicImportVarsOptions?.exclude, [/./]); assert.deepEqual(build.ssr, undefined); @@ -225,7 +239,9 @@ test('command: build, mode: production', async () => { assert.deepEqual(plugin.enforce, 'pre'); assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'dist'))); assert.deepEqual(build.emptyOutDir, undefined); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]'); assert.deepEqual(outputOptions.chunkFileNames, 'build/q-[hash].js'); @@ -267,7 +283,9 @@ test('command: build, --mode production (client)', async () => { assert.deepEqual(opts.target, 'client'); assert.deepEqual(opts.buildMode, 'production'); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'root'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'root')), + ]); assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'client-dist'))); assert.deepEqual(build.emptyOutDir, undefined); }); @@ -296,7 +314,9 @@ test('command: build, --ssr entry.server.tsx', async () => { assert.deepEqual(plugin.enforce, 'pre'); assert.deepEqual(build.outDir, normalizePath(resolve(cwd, 'server'))); assert.deepEqual(build.emptyOutDir, undefined); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'entry.server.tsx'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'entry.server.tsx')), + ]); assert.deepEqual(outputOptions.assetFileNames, 'assets/[hash]-[name].[ext]'); assert.isFunction(outputOptions.chunkFileNames); @@ -337,7 +357,9 @@ test('command: serve, --mode ssr', async () => { assert.deepEqual(opts.buildMode, 'development'); assert.deepEqual(build.minify, undefined); assert.deepEqual(build.ssr, undefined); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'renderz.tsx'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'renderz.tsx')), + ]); assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'ssr-dist'))); assert.deepEqual(build.emptyOutDir, undefined); assert.deepEqual(c.publicDir, undefined); @@ -366,7 +388,9 @@ test('command: serve, --mode ssr with build.assetsDir', async () => { assert.deepEqual(opts.buildMode, 'development'); assert.deepEqual(build.minify, undefined); assert.deepEqual(build.ssr, undefined); - assert.deepEqual(rollupOptions.input, [normalizePath(resolve(cwd, 'src', 'renderz.tsx'))]); + assert.deepEqual((rollupOptions.input as string[]).map(normalizePath), [ + normalizePath(resolve(cwd, 'src', 'renderz.tsx')), + ]); assert.deepEqual(c.build.outDir, normalizePath(resolve(cwd, 'ssr-dist'))); assert.deepEqual(build.emptyOutDir, undefined); assert.deepEqual(c.publicDir, undefined);