nx/packages/vite/src/utils/vite-config-edit-utils.spec.ts
Leosvel Pérez Espinosa 6684fc0688
fix(vite)!: generate config with esm by default (#29270)
BREAKING CHANGE

When generating projects that use Vite, the Vite configuration will be
set to use the ESM format only. Previously, the configuration was set to
produce both ESM and CJS, but the dual format was not correctly
configured in the libraries' `package.json` files, nor was it producing
the correct declaration files.

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
2024-12-10 11:58:51 +01:00

445 lines
15 KiB
TypeScript

import { Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { tsquery } from '@phenomnomnominal/tsquery';
import {
buildOption,
buildOptionObject,
conditionalConfig,
configNoDefineConfig,
imports,
hasEverything,
noBuildOptions,
noBuildOptionsHasTestOption,
noContentDefineConfig,
plugins,
someBuildOptions,
someBuildOptionsSomeTestOption,
testOption,
testOptionObject,
} from './test-files/test-vite-configs';
import { ensureViteConfigIsCorrect } from './vite-config-edit-utils';
describe('ensureViteConfigIsCorrect', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
});
it("should add build options if build options don't exist", () => {
tree.write('apps/my-app/vite.config.ts', noBuildOptions);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
const file = tsquery.ast(appFileContent);
const buildNode = tsquery.query(
file,
'PropertyAssignment:has(Identifier[name="build"])'
);
expect(buildNode).toBeDefined();
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'my-app',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es']
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime']
}
},cacheDir: '../../node_modules/.vitest',
plugins: [react(), nxViteTsPaths(), ],
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});
"
`);
});
it('should add new build options if some build options already exist', () => {
tree.write('apps/my-app/vite.config.ts', someBuildOptions);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
const file = tsquery.ast(appFileContent);
const buildNode = tsquery.query(
file,
'PropertyAssignment:has(Identifier[name="build"])'
);
expect(buildNode).toBeDefined();
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
cacheDir: '../../node_modules/.vitest',
plugins: [react(), nxViteTsPaths(), ],
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
build: {
'my': 'option',
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es"]},
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
}
});
"
`);
});
it('should add build and test options if defineConfig is empty', () => {
tree.write('apps/my-app/vite.config.ts', noContentDefineConfig);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
const file = tsquery.ast(appFileContent);
const buildNode = tsquery.query(
file,
'PropertyAssignment:has(Identifier[name="build"])'
);
expect(buildNode).toBeDefined();
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
plugins: [react(), nxViteTsPaths()],build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'my-app',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es']
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime']
}
},test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},});
"
`);
});
it('should add build options if it is using conditional config - do nothing for test', () => {
tree.write('apps/my-app/vite.config.ts', conditionalConfig);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
const file = tsquery.ast(appFileContent);
const buildNode = tsquery.query(
file,
'PropertyAssignment:has(Identifier[name="build"])'
);
expect(buildNode).toBeDefined();
expect(appFileContent).toMatchSnapshot();
});
it('should add build options if defineConfig is not used', () => {
tree.write('apps/my-app/vite.config.ts', configNoDefineConfig);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
const file = tsquery.ast(appFileContent);
const buildNode = tsquery.query(
file,
'PropertyAssignment:has(Identifier[name="build"])'
);
expect(buildNode).toBeDefined();
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default {
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'my-app',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es']
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime']
}
},test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
plugins: [react(), nxViteTsPaths(), ],
};
"
`);
});
it('should not do anything if cannot understand syntax of vite config', () => {
tree.write('apps/my-app/vite.config.ts', `console.log('Unknown syntax')`);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: false }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
expect(appFileContent).toMatchSnapshot();
});
it('should not do anything if project has everything setup already', () => {
tree.write('apps/my-app/vite.config.ts', hasEverything);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: true, test: true, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
expect(appFileContent).toMatchInlineSnapshot(`
"
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit';
export default defineConfig({
cacheDir: '../../node_modules/.vitest',
plugins: [dts({ entryRoot: 'src', tsConfigFilePath: joinPathFragments(__dirname, 'tsconfig.lib.json'), skipDiagnostics: true }), react(), nxViteTsPaths(), ],
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'pure-libs-react-vite',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es'],
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime'],
},
},
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});
"
`);
});
it('should add build option but not update test option if test already setup', () => {
tree.write('apps/my-app/vite.config.ts', noBuildOptionsHasTestOption);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: true, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
// Configuration for building your library.
// See: https://vitejs.dev/guide/build.html#library-mode
build: {
lib: {
// Could also be a dictionary or array of multiple entry points.
entry: 'src/index.ts',
name: 'my-app',
fileName: 'index',
// Change this to the formats you want to support.
// Don't forget to update your package.json as well.
formats: ['es']
},
rollupOptions: {
// External packages that should not be bundled into your library.
external: ['react', 'react-dom', 'react/jsx-runtime']
}
},cacheDir: '../../node_modules/.vitest',
plugins: [react(), nxViteTsPaths(), ],
test: {
globals: true,
environment: 'jsdom',
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
},
});
"
`);
});
it('should update both test and build options - keep existing settings', () => {
tree.write('apps/my-app/vite.config.ts', someBuildOptionsSomeTestOption);
ensureViteConfigIsCorrect(
tree,
'apps/my-app/vite.config.ts',
buildOption,
buildOptionObject,
imports,
plugins,
testOption,
testOptionObject,
'',
{ build: false, test: false, serve: true }
);
const appFileContent = tree.read('apps/my-app/vite.config.ts', 'utf-8');
expect(appFileContent).toMatchInlineSnapshot(`
"import dts from 'vite-plugin-dts';
import { joinPathFragments } from '@nx/devkit'
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
export default defineConfig({
plugins: [react(), nxViteTsPaths(), ],
test: {
'my': 'option',
'globals': true,
'environment': "jsdom",
'include': ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
},
build: {
'my': 'option',
'lib': {"entry":"src/index.ts","name":"my-app","fileName":"index","formats":["es"]},
'rollupOptions': {"external":["react","react-dom","react/jsx-runtime"]},
}
});
"
`);
});
});