feat(angular): add vitest option to angular (#27311)
- This adds `vitest` option to `unitTestRunner` for Angular generators. - This **does not** add vitest option to `create-nx-workspace` but I think we should provide this as an option in the future. Please let me know if you wantme to add this here or as a future feature. --------- Co-authored-by: Colum Ferry <cferry09@gmail.com>
This commit is contained in:
parent
c0c7ad7efc
commit
9fe8274367
@ -96,8 +96,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -51,8 +51,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests of the remote if it needs to be created.",
|
"description": "Test runner to use for unit tests of the remote if it needs to be created.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -105,8 +105,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -88,8 +88,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"importPath": {
|
"importPath": {
|
||||||
|
|||||||
@ -99,8 +99,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -568,4 +568,21 @@ describe('Angular Projects', () => {
|
|||||||
runCLI(`server ${webpackApp} --output-hashing none`)
|
runCLI(`server ${webpackApp} --output-hashing none`)
|
||||||
).toThrow();
|
).toThrow();
|
||||||
}, 500_000);
|
}, 500_000);
|
||||||
|
|
||||||
|
it('should generate apps and libs with vitest', async () => {
|
||||||
|
const app = uniq('app');
|
||||||
|
const lib = uniq('lib');
|
||||||
|
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/angular:app ${app} --unit-test-runner=vitest --no-interactive`
|
||||||
|
);
|
||||||
|
runCLI(
|
||||||
|
`generate @nx/angular:lib ${lib} --unit-test-runner=vitest --no-interactive`
|
||||||
|
);
|
||||||
|
|
||||||
|
// Make sure we are using vitest
|
||||||
|
checkFilesExist(`${app}/vite.config.mts`, `${lib}/vite.config.mts`);
|
||||||
|
|
||||||
|
runCLI(`run-many --target test --projects=${app},${lib} --parallel`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -427,6 +427,146 @@ exports[`app --strict should enable strict type checking: e2e tsconfig.json 1`]
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`app --unit-test-runner vitest should add tsconfig.spec.json 1`] = `
|
||||||
|
"{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../dist/out-tsc",
|
||||||
|
"types": [
|
||||||
|
"vitest/globals",
|
||||||
|
"vitest/importMeta",
|
||||||
|
"vite/client",
|
||||||
|
"node",
|
||||||
|
"vitest"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"vite.config.ts",
|
||||||
|
"vitest.config.ts",
|
||||||
|
"src/**/*.test.ts",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.test.tsx",
|
||||||
|
"src/**/*.spec.tsx",
|
||||||
|
"src/**/*.test.js",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.test.jsx",
|
||||||
|
"src/**/*.spec.jsx",
|
||||||
|
"src/**/*.d.ts"
|
||||||
|
],
|
||||||
|
"files": ["src/test-setup.ts"]
|
||||||
|
}
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`app --unit-test-runner vitest should generate src/test-setup.ts 1`] = `
|
||||||
|
"import '@analogjs/vitest-angular/setup-zone';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting,
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting()
|
||||||
|
);
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`app --unit-test-runner vitest should generate vite.config.mts 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import angular from '@analogjs/vite-plugin-angular';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
test: {
|
||||||
|
watch: false,
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
setupFiles: ['src/test-setup.ts'],
|
||||||
|
reporters: ['default'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/my-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`app --unit-test-runner vitest should generate vite.config.mts if package type is module 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import angular from '@analogjs/vite-plugin-angular';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
test: {
|
||||||
|
watch: false,
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
setupFiles: ['src/test-setup.ts'],
|
||||||
|
reporters: ['default'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/my-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`app --unit-test-runner vitest should generate vite.config.mts if workspace package type is module 1`] = `
|
||||||
|
"/// <reference types='vitest' />
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import angular from '@analogjs/vite-plugin-angular';
|
||||||
|
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
|
||||||
|
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
|
plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
|
||||||
|
// Uncomment this if you are using workers.
|
||||||
|
// worker: {
|
||||||
|
// plugins: [ nxViteTsPaths() ],
|
||||||
|
// },
|
||||||
|
test: {
|
||||||
|
watch: false,
|
||||||
|
globals: true,
|
||||||
|
environment: 'jsdom',
|
||||||
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
|
setupFiles: ['src/test-setup.ts'],
|
||||||
|
reporters: ['default'],
|
||||||
|
coverage: {
|
||||||
|
reportsDirectory: '../coverage/my-app',
|
||||||
|
provider: 'v8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`app angular compat support should import "ApplicationConfig" from "@angular/platform-browser" 1`] = `
|
exports[`app angular compat support should import "ApplicationConfig" from "@angular/platform-browser" 1`] = `
|
||||||
"import { ApplicationConfig } from '@angular/core';
|
"import { ApplicationConfig } from '@angular/core';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
||||||
import type { Tree } from '@nx/devkit';
|
import { Tree, writeJson } from '@nx/devkit';
|
||||||
import * as devkit from '@nx/devkit';
|
import * as devkit from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
NxJsonConfiguration,
|
NxJsonConfiguration,
|
||||||
@ -698,6 +698,110 @@ describe('app', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('vitest', () => {
|
||||||
|
it('should generate vite.config.mts', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
skipFormat: false,
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
appTree.read('my-app/vite.config.mts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate src/test-setup.ts', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
appTree.read('my-app/src/test-setup.ts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should exclude src/test-setup.ts in tsconfig.app.json', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tsConfig = readJson(appTree, 'my-app/tsconfig.app.json');
|
||||||
|
expect(tsConfig.exclude).toContain('src/test-setup.ts');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add tsconfig.spec.json', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
appTree.read('my-app/tsconfig.spec.json', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a reference to tsconfig.spec.json in tsconfig.json', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { references } = readJson(appTree, 'my-app/tsconfig.json');
|
||||||
|
expect(references).toContainEqual({
|
||||||
|
path: './tsconfig.spec.json',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add @nx/vite dependency', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { devDependencies } = readJson(appTree, 'package.json');
|
||||||
|
expect(devDependencies['@nx/vite']).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add vitest-angular', async () => {
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { devDependencies } = readJson(appTree, 'package.json');
|
||||||
|
expect(devDependencies['@analogjs/vite-plugin-angular']).toBeDefined();
|
||||||
|
expect(devDependencies['@analogjs/vitest-angular']).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate vite.config.mts if package type is module', async () => {
|
||||||
|
writeJson(appTree, 'my-app/package.json', {
|
||||||
|
name: 'my-app',
|
||||||
|
type: 'module',
|
||||||
|
});
|
||||||
|
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
skipFormat: false,
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
appTree.read('my-app/vite.config.mts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate vite.config.mts if workspace package type is module', async () => {
|
||||||
|
updateJson(appTree, 'package.json', (json) => ({
|
||||||
|
...json,
|
||||||
|
type: 'module',
|
||||||
|
}));
|
||||||
|
|
||||||
|
await generateApp(appTree, 'my-app', {
|
||||||
|
skipFormat: false,
|
||||||
|
unitTestRunner: UnitTestRunner.Vitest,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
appTree.read('my-app/vite.config.mts', 'utf-8')
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('none', () => {
|
describe('none', () => {
|
||||||
it('should not generate test configuration', async () => {
|
it('should not generate test configuration', async () => {
|
||||||
await generateApp(appTree, 'my-app', {
|
await generateApp(appTree, 'my-app', {
|
||||||
|
|||||||
@ -1,15 +1,26 @@
|
|||||||
import { Tree } from '@nx/devkit';
|
import { Tree } from '@nx/devkit';
|
||||||
import { UnitTestRunner } from '../../../utils/test-runners';
|
import { UnitTestRunner } from '../../../utils/test-runners';
|
||||||
import { addJest } from '../../utils/add-jest';
|
import { addJest } from '../../utils/add-jest';
|
||||||
|
import { addVitest } from '../../utils/add-vitest';
|
||||||
import type { NormalizedSchema } from './normalized-schema';
|
import type { NormalizedSchema } from './normalized-schema';
|
||||||
|
|
||||||
export async function addUnitTestRunner(host: Tree, options: NormalizedSchema) {
|
export async function addUnitTestRunner(host: Tree, options: NormalizedSchema) {
|
||||||
if (options.unitTestRunner === UnitTestRunner.Jest) {
|
switch (options.unitTestRunner) {
|
||||||
await addJest(host, {
|
case UnitTestRunner.Jest:
|
||||||
name: options.name,
|
await addJest(host, {
|
||||||
projectRoot: options.appProjectRoot,
|
name: options.name,
|
||||||
skipPackageJson: options.skipPackageJson,
|
projectRoot: options.appProjectRoot,
|
||||||
strict: options.strict,
|
skipPackageJson: options.skipPackageJson,
|
||||||
});
|
strict: options.strict,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case UnitTestRunner.Vitest:
|
||||||
|
await addVitest(host, {
|
||||||
|
name: options.name,
|
||||||
|
projectRoot: options.appProjectRoot,
|
||||||
|
skipPackageJson: options.skipPackageJson,
|
||||||
|
strict: options.strict,
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,8 +99,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -51,8 +51,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests of the remote if it needs to be created.",
|
"description": "Test runner to use for unit tests of the remote if it needs to be created.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -108,8 +108,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
@ -30,6 +30,8 @@ import { addJest } from '../utils/add-jest';
|
|||||||
import { setGeneratorDefaults } from './lib/set-generator-defaults';
|
import { setGeneratorDefaults } from './lib/set-generator-defaults';
|
||||||
import { ensureAngularDependencies } from '../utils/ensure-angular-dependencies';
|
import { ensureAngularDependencies } from '../utils/ensure-angular-dependencies';
|
||||||
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command';
|
||||||
|
import { UnitTestRunner } from '../../utils/test-runners';
|
||||||
|
import { addVitest } from '../utils/add-vitest';
|
||||||
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
import { assertNotUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
||||||
|
|
||||||
export async function libraryGenerator(
|
export async function libraryGenerator(
|
||||||
@ -130,13 +132,23 @@ async function addUnitTestRunner(
|
|||||||
host: Tree,
|
host: Tree,
|
||||||
options: NormalizedSchema['libraryOptions']
|
options: NormalizedSchema['libraryOptions']
|
||||||
) {
|
) {
|
||||||
if (options.unitTestRunner === 'jest') {
|
switch (options.unitTestRunner) {
|
||||||
await addJest(host, {
|
case UnitTestRunner.Jest:
|
||||||
name: options.name,
|
await addJest(host, {
|
||||||
projectRoot: options.projectRoot,
|
name: options.name,
|
||||||
skipPackageJson: options.skipPackageJson,
|
projectRoot: options.projectRoot,
|
||||||
strict: options.strict,
|
skipPackageJson: options.skipPackageJson,
|
||||||
});
|
strict: options.strict,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case UnitTestRunner.Vitest:
|
||||||
|
await addVitest(host, {
|
||||||
|
name: options.name,
|
||||||
|
projectRoot: options.projectRoot,
|
||||||
|
skipPackageJson: options.skipPackageJson,
|
||||||
|
strict: options.strict,
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -88,8 +88,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"importPath": {
|
"importPath": {
|
||||||
|
|||||||
@ -102,8 +102,9 @@
|
|||||||
},
|
},
|
||||||
"unitTestRunner": {
|
"unitTestRunner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jest", "none"],
|
"enum": ["jest", "vitest", "none"],
|
||||||
"description": "Test runner to use for unit tests.",
|
"description": "Test runner to use for unit tests.",
|
||||||
|
"x-prompt": "Which unit test runner would you like to use?",
|
||||||
"default": "jest"
|
"default": "jest"
|
||||||
},
|
},
|
||||||
"e2eTestRunner": {
|
"e2eTestRunner": {
|
||||||
|
|||||||
84
packages/angular/src/generators/utils/add-vitest.ts
Normal file
84
packages/angular/src/generators/utils/add-vitest.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import {
|
||||||
|
addDependenciesToPackageJson,
|
||||||
|
ensurePackage,
|
||||||
|
joinPathFragments,
|
||||||
|
type Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { analogVitestAngular, nxVersion } from '../../utils/versions';
|
||||||
|
|
||||||
|
export type AddVitestOptions = {
|
||||||
|
name: string;
|
||||||
|
projectRoot: string;
|
||||||
|
skipPackageJson: boolean;
|
||||||
|
strict: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function addVitest(
|
||||||
|
tree: Tree,
|
||||||
|
options: AddVitestOptions
|
||||||
|
): Promise<void> {
|
||||||
|
if (!options.skipPackageJson) {
|
||||||
|
addDependenciesToPackageJson(
|
||||||
|
tree,
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
'@analogjs/vitest-angular': analogVitestAngular,
|
||||||
|
'@analogjs/vite-plugin-angular': analogVitestAngular,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { createOrEditViteConfig, viteConfigurationGenerator } = ensurePackage<
|
||||||
|
typeof import('@nx/vite')
|
||||||
|
>('@nx/vite', nxVersion);
|
||||||
|
|
||||||
|
const relativeTestSetupPath = joinPathFragments('src', 'test-setup.ts');
|
||||||
|
|
||||||
|
const setupFile = joinPathFragments(
|
||||||
|
options.projectRoot,
|
||||||
|
relativeTestSetupPath
|
||||||
|
);
|
||||||
|
if (!tree.exists(setupFile)) {
|
||||||
|
tree.write(
|
||||||
|
setupFile,
|
||||||
|
`import '@analogjs/vitest-angular/setup-zone';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting,
|
||||||
|
} from '@angular/platform-browser-dynamic/testing';
|
||||||
|
import { getTestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
getTestBed().initTestEnvironment(
|
||||||
|
BrowserDynamicTestingModule,
|
||||||
|
platformBrowserDynamicTesting()
|
||||||
|
);
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
await viteConfigurationGenerator(tree, {
|
||||||
|
project: options.name,
|
||||||
|
newProject: true,
|
||||||
|
uiFramework: 'none',
|
||||||
|
includeVitest: true,
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
});
|
||||||
|
|
||||||
|
createOrEditViteConfig(
|
||||||
|
tree,
|
||||||
|
{
|
||||||
|
project: options.name,
|
||||||
|
includeLib: false,
|
||||||
|
includeVitest: true,
|
||||||
|
inSourceTests: false,
|
||||||
|
imports: [`import angular from '@analogjs/vite-plugin-angular'`],
|
||||||
|
plugins: ['angular()'],
|
||||||
|
setupFile: relativeTestSetupPath,
|
||||||
|
useEsmExtension: true,
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,13 +17,16 @@ export type PackageVersionNames =
|
|||||||
|
|
||||||
export type VersionMap = {
|
export type VersionMap = {
|
||||||
angularV16: Record<
|
angularV16: Record<
|
||||||
Exclude<CompatPackageVersionNames, 'typescriptEslintVersion'>,
|
Exclude<
|
||||||
|
CompatPackageVersionNames,
|
||||||
|
'analogVitestAngular' | 'typescriptEslintVersion'
|
||||||
|
>,
|
||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
angularV17: Record<
|
angularV17: Record<
|
||||||
Exclude<
|
Exclude<
|
||||||
CompatPackageVersionNames,
|
CompatPackageVersionNames,
|
||||||
'ngUniversalVersion' | 'typescriptEslintVersion'
|
'analogVitestAngular' | 'ngUniversalVersion' | 'typescriptEslintVersion'
|
||||||
>,
|
>,
|
||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
export enum UnitTestRunner {
|
export enum UnitTestRunner {
|
||||||
Jest = 'jest',
|
Jest = 'jest',
|
||||||
None = 'none',
|
None = 'none',
|
||||||
|
Vitest = 'vitest',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum E2eTestRunner {
|
export enum E2eTestRunner {
|
||||||
|
|||||||
@ -28,5 +28,6 @@ export const tsNodeVersion = '10.9.1';
|
|||||||
export const jestPresetAngularVersion = '~14.1.0';
|
export const jestPresetAngularVersion = '~14.1.0';
|
||||||
export const typesNodeVersion = '18.16.9';
|
export const typesNodeVersion = '18.16.9';
|
||||||
export const jasmineMarblesVersion = '^0.9.2';
|
export const jasmineMarblesVersion = '^0.9.2';
|
||||||
|
export const analogVitestAngular = '~1.9.1';
|
||||||
|
|
||||||
export const jsoncEslintParserVersion = '^2.1.0';
|
export const jsoncEslintParserVersion = '^2.1.0';
|
||||||
|
|||||||
@ -214,11 +214,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
server:{
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
preview:{
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
@ -244,7 +244,7 @@ export default defineConfig({
|
|||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-app',
|
reportsDirectory: '../coverage/my-app',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
@ -278,11 +278,11 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-app',
|
cacheDir: '../node_modules/.vite/my-app',
|
||||||
server:{
|
server: {
|
||||||
port: 4200,
|
port: 4200,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
preview:{
|
preview: {
|
||||||
port: 4300,
|
port: 4300,
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
},
|
},
|
||||||
@ -308,7 +308,7 @@ export default defineConfig({
|
|||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-app',
|
reportsDirectory: '../coverage/my-app',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -52,6 +52,7 @@ describe('app', () => {
|
|||||||
it('should add vite types to tsconfigs', async () => {
|
it('should add vite types to tsconfigs', async () => {
|
||||||
await applicationGenerator(appTree, {
|
await applicationGenerator(appTree, {
|
||||||
...schema,
|
...schema,
|
||||||
|
skipFormat: false,
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
});
|
});
|
||||||
@ -198,6 +199,7 @@ describe('app', () => {
|
|||||||
it('should use preview vite types to tsconfigs', async () => {
|
it('should use preview vite types to tsconfigs', async () => {
|
||||||
await applicationGenerator(appTree, {
|
await applicationGenerator(appTree, {
|
||||||
...schema,
|
...schema,
|
||||||
|
skipFormat: false,
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -39,7 +39,15 @@ import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
|
|||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
root: __dirname,
|
root: __dirname,
|
||||||
cacheDir: '../node_modules/.vite/my-lib',
|
cacheDir: '../node_modules/.vite/my-lib',
|
||||||
plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md']), dts({ entryRoot: 'src', tsconfigPath: path.join(__dirname, 'tsconfig.lib.json') })],
|
plugins: [
|
||||||
|
react(),
|
||||||
|
nxViteTsPaths(),
|
||||||
|
nxCopyAssetsPlugin(['*.md']),
|
||||||
|
dts({
|
||||||
|
entryRoot: 'src',
|
||||||
|
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
|
||||||
|
}),
|
||||||
|
],
|
||||||
// Uncomment this if you are using workers.
|
// Uncomment this if you are using workers.
|
||||||
// worker: {
|
// worker: {
|
||||||
// plugins: [ nxViteTsPaths() ],
|
// plugins: [ nxViteTsPaths() ],
|
||||||
@ -60,11 +68,11 @@ export default defineConfig({
|
|||||||
fileName: 'index',
|
fileName: 'index',
|
||||||
// Change this to the formats you want to support.
|
// Change this to the formats you want to support.
|
||||||
// Don't forget to update your package.json as well.
|
// Don't forget to update your package.json as well.
|
||||||
formats: ['es', 'cjs']
|
formats: ['es', 'cjs'],
|
||||||
},
|
},
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
// External packages that should not be bundled into your library.
|
// External packages that should not be bundled into your library.
|
||||||
external: ['react','react-dom','react/jsx-runtime']
|
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
test: {
|
test: {
|
||||||
@ -76,7 +84,7 @@ export default defineConfig({
|
|||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '../coverage/my-lib',
|
reportsDirectory: '../coverage/my-lib',
|
||||||
provider: 'v8',
|
provider: 'v8',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
"
|
"
|
||||||
|
|||||||
@ -70,6 +70,7 @@ describe('lib', () => {
|
|||||||
it('should add vite types to tsconfigs', async () => {
|
it('should add vite types to tsconfigs', async () => {
|
||||||
await libraryGenerator(tree, {
|
await libraryGenerator(tree, {
|
||||||
...defaultSchema,
|
...defaultSchema,
|
||||||
|
skipFormat: false,
|
||||||
bundler: 'vite',
|
bundler: 'vite',
|
||||||
unitTestRunner: 'vitest',
|
unitTestRunner: 'vitest',
|
||||||
});
|
});
|
||||||
|
|||||||
@ -73,6 +73,7 @@ describe('@nx/vite:init', () => {
|
|||||||
"default",
|
"default",
|
||||||
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
||||||
"!{projectRoot}/tsconfig.spec.json",
|
"!{projectRoot}/tsconfig.spec.json",
|
||||||
|
"!{projectRoot}/src/test-setup.[jt]s",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
@ -22,7 +22,8 @@ export function updateNxJsonSettings(tree: Tree) {
|
|||||||
if (productionFileSet) {
|
if (productionFileSet) {
|
||||||
productionFileSet.push(
|
productionFileSet.push(
|
||||||
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)',
|
'!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)',
|
||||||
'!{projectRoot}/tsconfig.spec.json'
|
'!{projectRoot}/tsconfig.spec.json',
|
||||||
|
'!{projectRoot}/src/test-setup.[jt]s'
|
||||||
);
|
);
|
||||||
|
|
||||||
nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
|
nxJson.namedInputs.production = Array.from(new Set(productionFileSet));
|
||||||
|
|||||||
@ -155,6 +155,8 @@ function updateTsConfig(
|
|||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
projectType: ProjectType
|
projectType: ProjectType
|
||||||
) {
|
) {
|
||||||
|
const setupFile = tryFindSetupFile(tree, projectRoot);
|
||||||
|
|
||||||
if (tree.exists(joinPathFragments(projectRoot, 'tsconfig.spec.json'))) {
|
if (tree.exists(joinPathFragments(projectRoot, 'tsconfig.spec.json'))) {
|
||||||
updateJson(
|
updateJson(
|
||||||
tree,
|
tree,
|
||||||
@ -168,6 +170,11 @@ function updateTsConfig(
|
|||||||
json.compilerOptions.types = ['vitest'];
|
json.compilerOptions.types = ['vitest'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (setupFile) {
|
||||||
|
json.files = [...(json.files ?? []), setupFile];
|
||||||
|
}
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -221,18 +228,11 @@ function updateTsConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.inSourceTests) {
|
if (tree.exists(runtimeTsconfigPath)) {
|
||||||
if (tree.exists(runtimeTsconfigPath)) {
|
updateJson(tree, runtimeTsconfigPath, (json) => {
|
||||||
updateJson(tree, runtimeTsconfigPath, (json) => {
|
if (options.inSourceTests) {
|
||||||
(json.compilerOptions.types ??= []).push('vitest/importMeta');
|
(json.compilerOptions.types ??= []).push('vitest/importMeta');
|
||||||
return json;
|
} else {
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addTsLibDependencies(tree);
|
|
||||||
} else {
|
|
||||||
if (tree.exists(runtimeTsconfigPath)) {
|
|
||||||
updateJson(tree, runtimeTsconfigPath, (json) => {
|
|
||||||
const uniqueExclude = new Set([
|
const uniqueExclude = new Set([
|
||||||
...(json.exclude || []),
|
...(json.exclude || []),
|
||||||
'vite.config.ts',
|
'vite.config.ts',
|
||||||
@ -247,14 +247,19 @@ function updateTsConfig(
|
|||||||
'src/**/*.spec.jsx',
|
'src/**/*.spec.jsx',
|
||||||
]);
|
]);
|
||||||
json.exclude = [...uniqueExclude];
|
json.exclude = [...uniqueExclude];
|
||||||
return json;
|
}
|
||||||
});
|
|
||||||
} else {
|
if (setupFile) {
|
||||||
logger.warn(
|
json.exclude = [...(json.exclude ?? []), setupFile];
|
||||||
`Couldn't find a runtime tsconfig file at ${runtimeTsconfigPath} to exclude the test files from. ` +
|
}
|
||||||
`If you're using a different filename for your runtime tsconfig, please provide it with the '--runtimeTsconfigFileName' flag.`
|
|
||||||
);
|
return json;
|
||||||
}
|
});
|
||||||
|
} else {
|
||||||
|
logger.warn(
|
||||||
|
`Couldn't find a runtime tsconfig file at ${runtimeTsconfigPath} to exclude the test files from. ` +
|
||||||
|
`If you're using a different filename for your runtime tsconfig, please provide it with the '--runtimeTsconfigFileName' flag.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,4 +295,11 @@ function getCoverageProviderDependency(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tryFindSetupFile(tree: Tree, projectRoot: string) {
|
||||||
|
const setupFile = joinPathFragments('src', 'test-setup.ts');
|
||||||
|
if (tree.exists(joinPathFragments(projectRoot, setupFile))) {
|
||||||
|
return setupFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default vitestGenerator;
|
export default vitestGenerator;
|
||||||
|
|||||||
@ -362,6 +362,8 @@ export interface ViteConfigFileOptions {
|
|||||||
imports?: string[];
|
imports?: string[];
|
||||||
plugins?: string[];
|
plugins?: string[];
|
||||||
coverageProvider?: 'v8' | 'istanbul' | 'custom';
|
coverageProvider?: 'v8' | 'istanbul' | 'custom';
|
||||||
|
setupFile?: string;
|
||||||
|
useEsmExtension?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOrEditViteConfig(
|
export function createOrEditViteConfig(
|
||||||
@ -371,11 +373,15 @@ export function createOrEditViteConfig(
|
|||||||
projectAlreadyHasViteTargets?: TargetFlags,
|
projectAlreadyHasViteTargets?: TargetFlags,
|
||||||
vitestFileName?: boolean
|
vitestFileName?: boolean
|
||||||
) {
|
) {
|
||||||
const { root: projectRoot } = readProjectConfiguration(tree, options.project);
|
const { root: projectRoot, projectType } = readProjectConfiguration(
|
||||||
|
tree,
|
||||||
|
options.project
|
||||||
|
);
|
||||||
|
|
||||||
|
const extension = options.useEsmExtension ? 'mts' : 'ts';
|
||||||
const viteConfigPath = vitestFileName
|
const viteConfigPath = vitestFileName
|
||||||
? `${projectRoot}/vitest.config.ts`
|
? `${projectRoot}/vitest.config.${extension}`
|
||||||
: `${projectRoot}/vite.config.ts`;
|
: `${projectRoot}/vite.config.${extension}`;
|
||||||
|
|
||||||
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
const isUsingTsPlugin = isUsingTsSolutionSetup(tree);
|
||||||
const buildOutDir = isUsingTsPlugin
|
const buildOutDir = isUsingTsPlugin
|
||||||
@ -453,12 +459,13 @@ export function createOrEditViteConfig(
|
|||||||
watch: false,
|
watch: false,
|
||||||
globals: true,
|
globals: true,
|
||||||
environment: '${options.testEnvironment ?? 'jsdom'}',
|
environment: '${options.testEnvironment ?? 'jsdom'}',
|
||||||
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],${
|
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
|
||||||
options.inSourceTests
|
${options.setupFile ? ` setupFiles: ['${options.setupFile}'],\n` : ''}\
|
||||||
? `
|
${
|
||||||
includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],`
|
options.inSourceTests
|
||||||
: ''
|
? ` includeSource: ['src/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],\n`
|
||||||
}
|
: ''
|
||||||
|
}\
|
||||||
reporters: ['default'],
|
reporters: ['default'],
|
||||||
coverage: {
|
coverage: {
|
||||||
reportsDirectory: '${reportsDirectory}',
|
reportsDirectory: '${reportsDirectory}',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user