375 lines
12 KiB
TypeScript
375 lines
12 KiB
TypeScript
import {
|
|
addDependenciesToPackageJson,
|
|
addProjectConfiguration,
|
|
readJson,
|
|
Tree,
|
|
} from '@nx/devkit';
|
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
import { nxVersion } from '../../utils/versions';
|
|
|
|
import { viteConfigurationGenerator } from './configuration';
|
|
import {
|
|
mockAngularAppGenerator,
|
|
mockReactAppGenerator,
|
|
mockReactLibNonBuildableJestTestRunnerGenerator,
|
|
mockReactLibNonBuildableVitestRunnerGenerator,
|
|
mockReactMixedAppGenerator,
|
|
mockUnknownAppGenerator,
|
|
mockWebAppGenerator,
|
|
} from '../../utils/test-utils';
|
|
|
|
describe('@nx/vite:configuration', () => {
|
|
let tree: Tree;
|
|
|
|
describe('transform React app to use Vite', () => {
|
|
beforeAll(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockReactAppGenerator(tree);
|
|
const existing = 'existing';
|
|
const existingVersion = '1.0.0';
|
|
addDependenciesToPackageJson(
|
|
tree,
|
|
{ '@nx/vite': nxVersion, [existing]: existingVersion },
|
|
{ [existing]: existingVersion }
|
|
);
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
project: 'my-test-react-app',
|
|
});
|
|
});
|
|
|
|
it('should add vite packages and react-related dependencies for vite', async () => {
|
|
const packageJson = readJson(tree, '/package.json');
|
|
expect(packageJson.devDependencies).toMatchObject({
|
|
vite: expect.any(String),
|
|
'@vitejs/plugin-react': expect.any(String),
|
|
});
|
|
});
|
|
|
|
it('should move index.html to the root of the project', () => {
|
|
expect(tree.exists('apps/my-test-react-app/src/index.html')).toBeFalsy();
|
|
expect(tree.exists('apps/my-test-react-app/index.html')).toBeTruthy();
|
|
expect(
|
|
tree.read('apps/my-test-react-app/index.html', 'utf-8')
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
it('should create correct tsconfig compilerOptions', () => {
|
|
const tsconfigJson = readJson(
|
|
tree,
|
|
'apps/my-test-react-app/tsconfig.json'
|
|
);
|
|
expect(tsconfigJson.compilerOptions.types).toMatchObject(['vite/client']);
|
|
});
|
|
|
|
it('should create vite.config file at the root of the app', () => {
|
|
expect(tree.exists('apps/my-test-react-app/vite.config.ts')).toBe(true);
|
|
expect(
|
|
tree.read('apps/my-test-react-app/vite.config.ts', 'utf-8')
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
it('should transform workspace.json project config', () => {
|
|
expect(tree.read('workspace.json', 'utf-8')).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('transform Web app to use Vite', () => {
|
|
beforeAll(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockWebAppGenerator(tree);
|
|
const existing = 'existing';
|
|
const existingVersion = '1.0.0';
|
|
addDependenciesToPackageJson(
|
|
tree,
|
|
{ '@nx/vite': nxVersion, [existing]: existingVersion },
|
|
{ [existing]: existingVersion }
|
|
);
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-web-app',
|
|
});
|
|
});
|
|
it('should add vite dependencies for vite', async () => {
|
|
const packageJson = readJson(tree, '/package.json');
|
|
expect(packageJson.devDependencies).toMatchObject({
|
|
vite: expect.any(String),
|
|
'vite-tsconfig-paths': expect.any(String),
|
|
});
|
|
});
|
|
|
|
it('should move index.html to the root of the project', () => {
|
|
expect(tree.exists('apps/my-test-web-app/src/index.html')).toBeFalsy();
|
|
expect(tree.exists('apps/my-test-web-app/index.html')).toBeTruthy();
|
|
expect(
|
|
tree.read('apps/my-test-web-app/index.html', 'utf-8')
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
it('should create correct tsconfig compilerOptions', () => {
|
|
const tsconfigJson = readJson(tree, 'apps/my-test-web-app/tsconfig.json');
|
|
expect(tsconfigJson.compilerOptions.types).toMatchObject(['vite/client']);
|
|
});
|
|
|
|
it('should create vite.config file at the root of the app', () => {
|
|
expect(tree.exists('apps/my-test-web-app/vite.config.ts')).toBe(true);
|
|
expect(
|
|
tree.read('apps/my-test-web-app/vite.config.ts', 'utf-8')
|
|
).toMatchSnapshot();
|
|
});
|
|
|
|
it('should transform workspace.json project config', () => {
|
|
expect(tree.read('workspace.json', 'utf-8')).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('do not transform Angular app to use Vite', () => {
|
|
beforeAll(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockAngularAppGenerator(tree);
|
|
});
|
|
it('should throw when trying to convert', async () => {
|
|
expect.assertions(2);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-angular-app',
|
|
});
|
|
} catch (e) {
|
|
expect(e).toBeDefined();
|
|
expect(e.toString()).toContain(
|
|
'The project my-test-angular-app cannot be converted to use the @nx/vite executors'
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('inform user of unknown targets when converting', () => {
|
|
beforeAll(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockUnknownAppGenerator(tree);
|
|
});
|
|
|
|
it('should throw when trying to convert something unknown', async () => {
|
|
const { Confirm } = require('enquirer');
|
|
const confirmSpy = jest.spyOn(Confirm.prototype, 'run');
|
|
confirmSpy.mockResolvedValue(true);
|
|
expect.assertions(2);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-random-app',
|
|
});
|
|
} catch (e) {
|
|
expect(e).toBeDefined();
|
|
expect(e.toString()).toContain(
|
|
'Error: Cannot find apps/my-test-random-app/tsconfig.json'
|
|
);
|
|
}
|
|
});
|
|
|
|
it('should throw when trying to convert something unknown and user denies conversion', async () => {
|
|
const { Confirm } = require('enquirer');
|
|
const confirmSpy = jest.spyOn(Confirm.prototype, 'run');
|
|
confirmSpy.mockResolvedValue(false);
|
|
|
|
expect.assertions(2);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-random-app',
|
|
});
|
|
} catch (e) {
|
|
expect(e).toBeDefined();
|
|
expect(e.toString()).toContain(
|
|
'Nx could not verify that the executors you are using can be converted to the @nx/vite executors.'
|
|
);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('transform React app to use Vite by providing custom targets', () => {
|
|
describe('transform React app if supported executor is provided', () => {
|
|
beforeEach(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockReactMixedAppGenerator(tree);
|
|
const existing = 'existing';
|
|
const existingVersion = '1.0.0';
|
|
addDependenciesToPackageJson(
|
|
tree,
|
|
{ '@nx/vite': nxVersion, [existing]: existingVersion },
|
|
{ [existing]: existingVersion }
|
|
);
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
project: 'my-test-mixed-react-app',
|
|
buildTarget: 'valid-build',
|
|
});
|
|
});
|
|
it('should add vite packages and react-related dependencies for vite', async () => {
|
|
const packageJson = readJson(tree, '/package.json');
|
|
expect(packageJson.devDependencies).toMatchObject({
|
|
vite: expect.any(String),
|
|
'@vitejs/plugin-react': expect.any(String),
|
|
});
|
|
});
|
|
|
|
it('should create vite.config file at the root of the app', () => {
|
|
expect(tree.exists('apps/my-test-mixed-react-app/vite.config.ts')).toBe(
|
|
true
|
|
);
|
|
});
|
|
|
|
it('should transform workspace.json project config', () => {
|
|
expect(tree.read('workspace.json', 'utf-8')).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('do NOT transform React app if unsupported executor is provided', () => {
|
|
beforeEach(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
mockReactMixedAppGenerator(tree);
|
|
const existing = 'existing';
|
|
const existingVersion = '1.0.0';
|
|
addDependenciesToPackageJson(
|
|
tree,
|
|
{ '@nx/vite': nxVersion, [existing]: existingVersion },
|
|
{ [existing]: existingVersion }
|
|
);
|
|
});
|
|
it('should throw when trying to convert and user denies', async () => {
|
|
const { Confirm } = require('enquirer');
|
|
const confirmSpy = jest.spyOn(Confirm.prototype, 'run');
|
|
confirmSpy.mockResolvedValue(false);
|
|
expect.assertions(2);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-mixed-react-app',
|
|
buildTarget: 'invalid-build',
|
|
});
|
|
} catch (e) {
|
|
expect(e).toBeDefined();
|
|
expect(e.toString()).toContain(
|
|
'The build target invalid-build cannot be converted to use the @nx/vite:build executor'
|
|
);
|
|
}
|
|
});
|
|
|
|
it('should NOT throw error when trying to convert and user confirms', async () => {
|
|
const { Confirm } = require('enquirer');
|
|
const confirmSpy = jest.spyOn(Confirm.prototype, 'run');
|
|
confirmSpy.mockResolvedValue(true);
|
|
expect.assertions(1);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'none',
|
|
project: 'my-test-mixed-react-app',
|
|
buildTarget: 'invalid-build',
|
|
});
|
|
expect(
|
|
tree.exists('apps/my-test-mixed-react-app/vite.config.ts')
|
|
).toBe(true);
|
|
} catch (e) {
|
|
throw new Error('Should not throw error');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('vitest', () => {
|
|
beforeAll(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
await mockReactAppGenerator(tree);
|
|
const existing = 'existing';
|
|
const existingVersion = '1.0.0';
|
|
addDependenciesToPackageJson(
|
|
tree,
|
|
{ '@nx/vite': nxVersion, [existing]: existingVersion },
|
|
{ [existing]: existingVersion }
|
|
);
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
project: 'my-test-react-app',
|
|
includeVitest: true,
|
|
});
|
|
});
|
|
it('should create a vitest configuration if "includeVitest" is true', () => {
|
|
const viteConfig = tree
|
|
.read('apps/my-test-react-app/vite.config.ts')
|
|
.toString();
|
|
expect(viteConfig).toContain('test');
|
|
expect(
|
|
tree.read('apps/my-test-react-app/vite.config.ts', 'utf-8')
|
|
).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe('library mode', () => {
|
|
beforeEach(async () => {
|
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
});
|
|
|
|
it('should add config for building library', async () => {
|
|
addProjectConfiguration(tree, 'my-lib', {
|
|
root: 'my-lib',
|
|
});
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
includeLib: true,
|
|
project: 'my-lib',
|
|
newProject: true,
|
|
});
|
|
|
|
const viteConfig = tree.read('my-lib/vite.config.ts').toString();
|
|
|
|
expect(viteConfig).toMatch('build: {');
|
|
expect(viteConfig).toMatch("external: ['react'");
|
|
expect(tree.read('my-lib/vite.config.ts', 'utf-8')).toMatchSnapshot();
|
|
});
|
|
|
|
it('should set up non buildable library correctly', async () => {
|
|
mockReactLibNonBuildableJestTestRunnerGenerator(tree);
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
project: 'react-lib-nonb-jest',
|
|
includeVitest: true,
|
|
});
|
|
expect(
|
|
tree.read('libs/react-lib-nonb-jest/vite.config.ts', 'utf-8')
|
|
).toMatchSnapshot();
|
|
|
|
expect(tree.read('workspace.json', 'utf-8')).toMatchSnapshot();
|
|
});
|
|
|
|
it('should set up non buildable library which already has vite.config.ts correctly', async () => {
|
|
const { Confirm } = require('enquirer');
|
|
const confirmSpy = jest.spyOn(Confirm.prototype, 'run');
|
|
confirmSpy.mockResolvedValue(true);
|
|
expect.assertions(2);
|
|
|
|
mockReactLibNonBuildableVitestRunnerGenerator(tree);
|
|
|
|
try {
|
|
await viteConfigurationGenerator(tree, {
|
|
uiFramework: 'react',
|
|
project: 'react-lib-nonb-vitest',
|
|
includeVitest: true,
|
|
});
|
|
expect(
|
|
tree.read('libs/react-lib-nonb-vitest/vite.config.ts', 'utf-8')
|
|
).toMatchSnapshot();
|
|
|
|
expect(tree.read('workspace.json', 'utf-8')).toMatchSnapshot();
|
|
} catch (e) {
|
|
throw new Error('Should not throw error');
|
|
}
|
|
});
|
|
});
|
|
});
|