Skip to content

Commit

Permalink
feat(angular): add vitest option to angular (#27311)
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
yjaaidi and Coly010 authored Oct 29, 2024
1 parent c0c7ad7 commit 9fe8274
Show file tree
Hide file tree
Showing 27 changed files with 481 additions and 66 deletions.
3 changes: 2 additions & 1 deletion docs/generated/packages/angular/generators/application.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"enum": ["jest", "vitest", "none"],
"description": "Test runner to use for unit tests.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@
},
"unitTestRunner": {
"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.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
3 changes: 2 additions & 1 deletion docs/generated/packages/angular/generators/host.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,9 @@
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"enum": ["jest", "vitest", "none"],
"description": "Test runner to use for unit tests.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
3 changes: 2 additions & 1 deletion docs/generated/packages/angular/generators/library.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,9 @@
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"enum": ["jest", "vitest", "none"],
"description": "Test runner to use for unit tests.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"importPath": {
Expand Down
3 changes: 2 additions & 1 deletion docs/generated/packages/angular/generators/remote.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"enum": ["jest", "vitest", "none"],
"description": "Test runner to use for unit tests.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
17 changes: 17 additions & 0 deletions e2e/angular/src/projects.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,4 +568,21 @@ describe('Angular Projects', () => {
runCLI(`server ${webpackApp} --output-hashing none`)
).toThrow();
}, 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`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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`] = `
"import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
Expand Down
106 changes: 105 additions & 1 deletion packages/angular/src/generators/application/application.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
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 {
NxJsonConfiguration,
Expand Down Expand Up @@ -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', () => {
it('should not generate test configuration', async () => {
await generateApp(appTree, 'my-app', {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import { Tree } from '@nx/devkit';
import { UnitTestRunner } from '../../../utils/test-runners';
import { addJest } from '../../utils/add-jest';
import { addVitest } from '../../utils/add-vitest';
import type { NormalizedSchema } from './normalized-schema';

export async function addUnitTestRunner(host: Tree, options: NormalizedSchema) {
if (options.unitTestRunner === UnitTestRunner.Jest) {
await addJest(host, {
name: options.name,
projectRoot: options.appProjectRoot,
skipPackageJson: options.skipPackageJson,
strict: options.strict,
});
switch (options.unitTestRunner) {
case UnitTestRunner.Jest:
await addJest(host, {
name: options.name,
projectRoot: options.appProjectRoot,
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;
}
}
3 changes: 2 additions & 1 deletion packages/angular/src/generators/application/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@
},
"unitTestRunner": {
"type": "string",
"enum": ["jest", "none"],
"enum": ["jest", "vitest", "none"],
"description": "Test runner to use for unit tests.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
3 changes: 2 additions & 1 deletion packages/angular/src/generators/federate-module/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@
},
"unitTestRunner": {
"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.",
"x-prompt": "Which unit test runner would you like to use?",
"default": "jest"
},
"e2eTestRunner": {
Expand Down
Loading

0 comments on commit 9fe8274

Please sign in to comment.