diff --git a/.github/workflows/e2e-matrix.yml b/.github/workflows/e2e-matrix.yml
index 8c936d4396..bbcf3e9adb 100644
--- a/.github/workflows/e2e-matrix.yml
+++ b/.github/workflows/e2e-matrix.yml
@@ -118,7 +118,8 @@ jobs:
- e2e-nx-misc
- e2e-nx-plugin
- e2e-nx-run
- - e2e-react
+ - e2e-react-core
+ - e2e-react-extensions
- e2e-react-native
- e2e-web
- e2e-rollup
@@ -172,7 +173,9 @@ jobs:
codeowners: 'S04SYHYKGNP'
- project: e2e-nx-run
codeowners: 'S04SYHYKGNP'
- - project: e2e-react
+ - project: e2e-react-core
+ codeowners: 'S04TNCNJG5N'
+ - project: e2e-react-extensions
codeowners: 'S04TNCNJG5N'
- project: e2e-react-native
codeowners: 'S04TNCNJG5N'
@@ -232,7 +235,9 @@ jobs:
- node_version: 16
project: e2e-lerna-smoke-tests
- node_version: 16
- project: e2e-react
+ project: e2e-react-core
+ - node_version: 16
+ project: e2e-react-extensions
- node_version: 16
project: e2e-react-native
- node_version: 16
@@ -278,7 +283,9 @@ jobs:
- node_version: 19
project: e2e-lerna-smoke-tests
- node_version: 19
- project: e2e-react
+ project: e2e-react-core
+ - node_version: 19
+ project: e2e-react-extensions
- node_version: 19
project: e2e-react-native
- node_version: 19
diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml
index 44917687f1..39d365fce3 100644
--- a/.github/workflows/e2e-windows.yml
+++ b/.github/workflows/e2e-windows.yml
@@ -87,7 +87,8 @@ jobs:
- e2e-nx-misc
- e2e-nx-plugin
- e2e-nx-run
- - e2e-react
+ - e2e-react-core
+ - e2e-react-extensions
- e2e-web
- e2e-rollup
- e2e-storybook
@@ -126,7 +127,9 @@ jobs:
codeowners: 'S04SYHYKGNP'
- project: e2e-nx-run
codeowners: 'S04SYHYKGNP'
- - project: e2e-react
+ - project: e2e-react-core
+ codeowners: 'S04TNCNJG5N'
+ - project: e2e-react-extensions
codeowners: 'S04TNCNJG5N'
- project: e2e-web
codeowners: 'S04SJ6PL98X'
@@ -173,7 +176,9 @@ jobs:
- node_version: 16
project: e2e-lerna-smoke-tests
- node_version: 16
- project: e2e-react
+ project: e2e-react-core
+ - node_version: 16
+ project: e2e-react-extensions
- node_version: 16
project: e2e-web
- node_version: 16
@@ -213,7 +218,9 @@ jobs:
- node_version: 19
project: e2e-lerna-smoke-tests
- node_version: 19
- project: e2e-react
+ project: e2e-react-core
+ - node_version: 19
+ project: e2e-react-extensions
- node_version: 19
project: e2e-web
- node_version: 19
diff --git a/CODEOWNERS b/CODEOWNERS
index 8ff9d36125..06cf682b0e 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -33,7 +33,8 @@ yarn.lock @FrozenPandaz @vsavkin @AgentEnder @jaysoo @JamesHenry
/docs/shared/packages/react/** @jaysoo @ndcunningham @mandarini @xiongemi
/docs/shared/packages/next/** @jaysoo @ndcunningham @xiongemi
/packages/react/** @jaysoo @ndcunningham @mandarini @xiongemi
-/e2e/react/** @jaysoo @mandarini @xiongemi @ndcunningham
+/e2e/react-core/** @jaysoo @mandarini @xiongemi @ndcunningham
+/e2e/react-extensions/** @jaysoo @mandarini @xiongemi @ndcunningham
/packages/next/** @ndcunningham @jaysoo @xiongemi
/e2e/next/** @ndcunningham @jaysoo @xiongemi
/packages/react/plugins/component-testing/** @jaysoo @ndcunningham @barbados-clemens
diff --git a/e2e/react/jest.config.ts b/e2e/react-core/jest.config.ts
similarity index 89%
rename from e2e/react/jest.config.ts
rename to e2e/react-core/jest.config.ts
index d1362b0be7..da8f01e5dd 100644
--- a/e2e/react/jest.config.ts
+++ b/e2e/react-core/jest.config.ts
@@ -6,6 +6,6 @@ export default {
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
maxWorkers: 1,
globals: {},
- displayName: 'e2e-react',
+ displayName: 'e2e-react-core',
preset: '../../jest.preset.js',
};
diff --git a/e2e/react/project.json b/e2e/react-core/project.json
similarity index 76%
rename from e2e/react/project.json
rename to e2e/react-core/project.json
index 79437b742c..45e531ced3 100644
--- a/e2e/react/project.json
+++ b/e2e/react-core/project.json
@@ -1,7 +1,7 @@
{
- "name": "e2e-react",
+ "name": "e2e-react-core",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
- "sourceRoot": "e2e/react",
+ "sourceRoot": "e2e/react-core",
"projectType": "application",
"targets": {
"e2e": {},
diff --git a/e2e/react/src/logo.svg b/e2e/react-core/src/logo.svg
similarity index 100%
rename from e2e/react/src/logo.svg
rename to e2e/react-core/src/logo.svg
diff --git a/e2e/react/src/react.module-federation.test.ts b/e2e/react-core/src/react-module-federation.test.ts
similarity index 98%
rename from e2e/react/src/react.module-federation.test.ts
rename to e2e/react-core/src/react-module-federation.test.ts
index 35893beb0c..b4536ba686 100644
--- a/e2e/react/src/react.module-federation.test.ts
+++ b/e2e/react-core/src/react-module-federation.test.ts
@@ -15,9 +15,9 @@ import {
describe('React Module Federation', () => {
let proj: string;
- beforeEach(() => (proj = newProject()));
+ beforeAll(() => (proj = newProject()));
- afterEach(() => cleanupProject());
+ afterAll(() => cleanupProject());
it('should generate host and remote apps', async () => {
const shell = uniq('shell');
diff --git a/e2e/react/src/react-package.test.ts b/e2e/react-core/src/react-package.test.ts
similarity index 64%
rename from e2e/react/src/react-package.test.ts
rename to e2e/react-core/src/react-package.test.ts
index c32226d682..b7f74165c0 100644
--- a/e2e/react/src/react-package.test.ts
+++ b/e2e/react-core/src/react-package.test.ts
@@ -264,130 +264,3 @@ export async function h() { return 'c'; }
}, 250000);
});
});
-
-describe('Build React applications and libraries with Vite', () => {
- let proj: string;
-
- beforeEach(() => {
- proj = newProject();
- });
-
- it('should test and lint app with bundler=vite', async () => {
- const viteApp = uniq('viteapp');
-
- runCLI(
- `generate @nrwl/react:app ${viteApp} --bundler=vite --unitTestRunner=vitest --no-interactive`
- );
-
- const appTestResults = await runCLIAsync(`test ${viteApp}`);
- expect(appTestResults.combinedOutput).toContain(
- 'Successfully ran target test'
- );
-
- const appLintResults = await runCLIAsync(`lint ${viteApp}`);
- expect(appLintResults.combinedOutput).toContain(
- 'Successfully ran target lint'
- );
-
- await runCLIAsync(`build ${viteApp}`);
- checkFilesExist(`dist/apps/${viteApp}/index.html`);
- }, 300_000);
-
- it('should test and lint app with bundler=vite and inSourceTests', async () => {
- const viteApp = uniq('viteapp');
- const viteLib = uniq('vitelib');
-
- runCLI(
- `generate @nrwl/react:app ${viteApp} --bundler=vite --unitTestRunner=vitest --inSourceTests --no-interactive`
- );
- expect(() => {
- checkFilesExist(`apps/${viteApp}/src/app/app.spec.tsx`);
- }).toThrow();
-
- const appTestResults = await runCLIAsync(`test ${viteApp}`);
- expect(appTestResults.combinedOutput).toContain(
- 'Successfully ran target test'
- );
-
- const appLintResults = await runCLIAsync(`lint ${viteApp}`);
- expect(appLintResults.combinedOutput).toContain(
- 'Successfully ran target lint'
- );
-
- await runCLIAsync(`build ${viteApp}`);
- checkFilesExist(`dist/apps/${viteApp}/index.html`);
-
- runCLI(
- `generate @nrwl/react:lib ${viteLib} --bundler=vite --inSourceTests --unitTestRunner=vitest --no-interactive`
- );
- expect(() => {
- checkFilesExist(`libs/${viteLib}/src/lib/${viteLib}.spec.tsx`);
- }).toThrow();
-
- runCLI(
- `generate @nrwl/react:component comp1 --inSourceTests --export --project=${viteLib} --no-interactive`
- );
- expect(() => {
- checkFilesExist(`libs/${viteLib}/src/lib/comp1/comp1.spec.tsx`);
- }).toThrow();
-
- runCLI(
- `generate @nrwl/react:component comp2 --export --project=${viteLib} --no-interactive`
- );
- checkFilesExist(`libs/${viteLib}/src/lib/comp2/comp2.spec.tsx`);
-
- const libTestResults = await runCLIAsync(`test ${viteLib}`);
- expect(libTestResults.combinedOutput).toContain(
- 'Successfully ran target test'
- );
-
- const libLintResults = await runCLIAsync(`lint ${viteLib}`);
- expect(libLintResults.combinedOutput).toContain(
- 'Successfully ran target lint'
- );
-
- await runCLIAsync(`build ${viteLib}`);
- checkFilesExist(
- `dist/libs/${viteLib}/index.d.ts`,
- `dist/libs/${viteLib}/index.js`,
- `dist/libs/${viteLib}/index.mjs`
- );
- }, 300_000);
-
- it('should support bundling with Vite', async () => {
- const viteLib = uniq('vitelib');
-
- runCLI(
- `generate @nrwl/react:lib ${viteLib} --bundler=vite --no-interactive --unit-test-runner=none`
- );
-
- const packageJson = readJson('package.json');
- // Vite does not need these libraries to work.
- expect(packageJson.dependencies['core-js']).toBeUndefined();
- expect(packageJson.dependencies['tslib']).toBeUndefined();
-
- await runCLIAsync(`build ${viteLib}`);
-
- checkFilesExist(
- `dist/libs/${viteLib}/package.json`,
- `dist/libs/${viteLib}/index.d.ts`,
- `dist/libs/${viteLib}/index.js`,
- `dist/libs/${viteLib}/index.mjs`
- );
-
- // Convert non-buildable lib to buildable one
- const nonBuildableLib = uniq('nonbuildablelib');
- runCLI(
- `generate @nrwl/react:lib ${nonBuildableLib} --no-interactive --unitTestRunner=jest`
- );
- runCLI(
- `generate @nrwl/vite:configuration ${nonBuildableLib} --uiFramework=react --no-interactive`
- );
- await runCLIAsync(`build ${nonBuildableLib}`);
- checkFilesExist(
- `dist/libs/${nonBuildableLib}/index.d.ts`,
- `dist/libs/${nonBuildableLib}/index.js`,
- `dist/libs/${nonBuildableLib}/index.mjs`
- );
- }, 300_000);
-});
diff --git a/e2e/react/src/react.test.ts b/e2e/react-core/src/react.test.ts
similarity index 56%
rename from e2e/react/src/react.test.ts
rename to e2e/react-core/src/react.test.ts
index 4fa7cc7af4..4eb5eeef3c 100644
--- a/e2e/react/src/react.test.ts
+++ b/e2e/react-core/src/react.test.ts
@@ -21,12 +21,12 @@ import { join } from 'path';
describe('React Applications', () => {
let proj: string;
- beforeEach(() => {
+ beforeAll(() => {
proj = newProject();
ensureCypressInstallation();
});
- afterEach(() => cleanupProject());
+ afterAll(() => cleanupProject());
it('should be able to generate a react app + lib (with CSR and SSR)', async () => {
const appName = uniq('app');
@@ -187,152 +187,183 @@ describe('React Applications', () => {
expect(await killPorts()).toBeTruthy();
}, 250_000);
- async function testGeneratedApp(
- appName,
- opts: {
- checkStyles: boolean;
- checkLinter: boolean;
- checkE2E: boolean;
- checkSourceMap?: boolean;
- }
- ) {
- if (opts.checkLinter) {
- const lintResults = runCLI(`lint ${appName}`);
- expect(lintResults).toContain('All files pass linting.');
- }
-
- runCLI(
- `build ${appName} --outputHashing none ${
- opts.checkSourceMap ? '--sourceMap' : ''
- }`
- );
- const filesToCheck = [
- `dist/apps/${appName}/index.html`,
- `dist/apps/${appName}/runtime.js`,
- `dist/apps/${appName}/main.js`,
- ];
-
- if (opts.checkSourceMap) {
- filesToCheck.push(`dist/apps/${appName}/main.js.map`);
- }
-
- if (opts.checkStyles) {
- filesToCheck.push(`dist/apps/${appName}/styles.css`);
- }
- checkFilesExist(...filesToCheck);
-
- if (opts.checkStyles) {
- expect(readFile(`dist/apps/${appName}/index.html`)).toContain(
- ''
- );
- }
-
- const testResults = await runCLIAsync(`test ${appName}`);
- expect(testResults.combinedOutput).toContain(
- 'Test Suites: 1 passed, 1 total'
- );
-
- if (opts.checkE2E && runCypressTests()) {
- const e2eResults = runCLI(`e2e ${appName}-e2e --no-watch`);
- expect(e2eResults).toContain('All specs passed!');
- expect(await killPorts()).toBeTruthy();
- }
- }
-});
-
-describe('React Applications: --style option', () => {
- // Only create workspace once
- beforeAll(() => newProject());
-
- it.each`
- style
- ${'css'}
- ${'scss'}
- ${'less'}
- ${'styl'}
- `('should support global and css modules', ({ style }) => {
+ it('should generate app with routing', async () => {
const appName = uniq('app');
- runCLI(
- `generate @nrwl/react:app ${appName} --style=${style} --bundler=webpack --no-interactive`
- );
- // make sure stylePreprocessorOptions works
- updateProjectConfig(appName, (config) => {
- config.targets.build.options.stylePreprocessorOptions = {
- includePaths: ['libs/shared/lib'],
- };
- return config;
- });
- updateFile(
- `apps/${appName}/src/styles.${style}`,
- `@import 'base.${style}';`
- );
- updateFile(
- `apps/${appName}/src/app/app.module.${style}`,
- (s) => `@import 'base.${style}';\n${s}`
- );
- updateFile(
- `libs/shared/lib/base.${style}`,
- `body { font-family: "Comic Sans MS"; }`
+ runCLI(
+ `generate @nrwl/react:app ${appName} --routing --bundler=webpack --no-interactive`
);
runCLI(`build ${appName} --outputHashing none`);
- expect(readFile(`dist/apps/${appName}/styles.css`)).toMatch(
- /Comic Sans MS/
+ checkFilesExist(
+ `dist/apps/${appName}/index.html`,
+ `dist/apps/${appName}/runtime.js`,
+ `dist/apps/${appName}/main.js`
);
- });
-});
+ }, 250_000);
-describe('React Applications and Libs with PostCSS', () => {
- let proj: string;
-
- beforeAll(() => (proj = newProject()));
-
- it('should support single path or auto-loading of PostCSS config files', async () => {
+ it('should be able to add a redux slice', async () => {
const appName = uniq('app');
const libName = uniq('lib');
runCLI(`g @nrwl/react:app ${appName} --bundler=webpack --no-interactive`);
+ runCLI(`g @nrwl/react:redux lemon --project=${appName}`);
runCLI(
- `g @nrwl/react:lib ${libName} --no-interactive --unit-test-runner=none`
+ `g @nrwl/react:lib ${libName} --unit-test-runner=jest --no-interactive`
+ );
+ runCLI(`g @nrwl/react:redux orange --project=${libName}`);
+
+ const appTestResults = await runCLIAsync(`test ${appName}`);
+ expect(appTestResults.combinedOutput).toContain(
+ 'Test Suites: 2 passed, 2 total'
);
- const mainPath = `apps/${appName}/src/main.tsx`;
- updateFile(
- mainPath,
- `import '@${proj}/${libName}';\n${readFile(mainPath)}`
+ const libTestResults = await runCLIAsync(`test ${libName}`);
+ expect(libTestResults.combinedOutput).toContain(
+ 'Test Suites: 2 passed, 2 total'
);
+ }, 250_000);
- createFile(
- `apps/${appName}/postcss.config.js`,
- `
+ describe('React Applications: --style option', () => {
+ it.each`
+ style
+ ${'css'}
+ ${'scss'}
+ ${'less'}
+ ${'styl'}
+ `('should support global and css modules', ({ style }) => {
+ const appName = uniq('app');
+ runCLI(
+ `generate @nrwl/react:app ${appName} --style=${style} --bundler=webpack --no-interactive`
+ );
+
+ // make sure stylePreprocessorOptions works
+ updateProjectConfig(appName, (config) => {
+ config.targets.build.options.stylePreprocessorOptions = {
+ includePaths: ['libs/shared/lib'],
+ };
+ return config;
+ });
+ updateFile(
+ `apps/${appName}/src/styles.${style}`,
+ `@import 'base.${style}';`
+ );
+ updateFile(
+ `apps/${appName}/src/app/app.module.${style}`,
+ (s) => `@import 'base.${style}';\n${s}`
+ );
+ updateFile(
+ `libs/shared/lib/base.${style}`,
+ `body { font-family: "Comic Sans MS"; }`
+ );
+
+ runCLI(`build ${appName} --outputHashing none`);
+
+ expect(readFile(`dist/apps/${appName}/styles.css`)).toMatch(
+ /Comic Sans MS/
+ );
+ });
+ });
+
+ describe('React Applications and Libs with PostCSS', () => {
+ it('should support single path or auto-loading of PostCSS config files', async () => {
+ const appName = uniq('app');
+ const libName = uniq('lib');
+
+ runCLI(`g @nrwl/react:app ${appName} --bundler=webpack --no-interactive`);
+ runCLI(
+ `g @nrwl/react:lib ${libName} --no-interactive --unit-test-runner=none`
+ );
+
+ const mainPath = `apps/${appName}/src/main.tsx`;
+ updateFile(
+ mainPath,
+ `import '@${proj}/${libName}';\n${readFile(mainPath)}`
+ );
+
+ createFile(
+ `apps/${appName}/postcss.config.js`,
+ `
console.log('HELLO FROM APP'); // need this output for e2e test
module.exports = {};
`
- );
- createFile(
- `libs/${libName}/postcss.config.js`,
- `
+ );
+ createFile(
+ `libs/${libName}/postcss.config.js`,
+ `
console.log('HELLO FROM LIB'); // need this output for e2e test
module.exports = {};
`
- );
+ );
- let buildResults = await runCLIAsync(`build ${appName}`);
+ let buildResults = await runCLIAsync(`build ${appName}`);
- expect(buildResults.combinedOutput).toMatch(/HELLO FROM APP/);
- expect(buildResults.combinedOutput).toMatch(/HELLO FROM LIB/);
+ expect(buildResults.combinedOutput).toMatch(/HELLO FROM APP/);
+ expect(buildResults.combinedOutput).toMatch(/HELLO FROM LIB/);
- // Only load app PostCSS config
- updateJson(`apps/${appName}/project.json`, (json) => {
- json.targets.build.options.postcssConfig = `apps/${appName}/postcss.config.js`;
- return json;
- });
+ // Only load app PostCSS config
+ updateJson(`apps/${appName}/project.json`, (json) => {
+ json.targets.build.options.postcssConfig = `apps/${appName}/postcss.config.js`;
+ return json;
+ });
- buildResults = await runCLIAsync(`build ${appName}`);
+ buildResults = await runCLIAsync(`build ${appName}`);
- expect(buildResults.combinedOutput).toMatch(/HELLO FROM APP/);
- expect(buildResults.combinedOutput).not.toMatch(/HELLO FROM LIB/);
- }, 250_000);
+ expect(buildResults.combinedOutput).toMatch(/HELLO FROM APP/);
+ expect(buildResults.combinedOutput).not.toMatch(/HELLO FROM LIB/);
+ }, 250_000);
+ });
});
+
+async function testGeneratedApp(
+ appName,
+ opts: {
+ checkStyles: boolean;
+ checkLinter: boolean;
+ checkE2E: boolean;
+ checkSourceMap?: boolean;
+ }
+) {
+ if (opts.checkLinter) {
+ const lintResults = runCLI(`lint ${appName}`);
+ expect(lintResults).toContain('All files pass linting.');
+ }
+
+ runCLI(
+ `build ${appName} --outputHashing none ${
+ opts.checkSourceMap ? '--sourceMap' : ''
+ }`
+ );
+ const filesToCheck = [
+ `dist/apps/${appName}/index.html`,
+ `dist/apps/${appName}/runtime.js`,
+ `dist/apps/${appName}/main.js`,
+ ];
+
+ if (opts.checkSourceMap) {
+ filesToCheck.push(`dist/apps/${appName}/main.js.map`);
+ }
+
+ if (opts.checkStyles) {
+ filesToCheck.push(`dist/apps/${appName}/styles.css`);
+ }
+ checkFilesExist(...filesToCheck);
+
+ if (opts.checkStyles) {
+ expect(readFile(`dist/apps/${appName}/index.html`)).toContain(
+ ''
+ );
+ }
+
+ const testResults = await runCLIAsync(`test ${appName}`);
+ expect(testResults.combinedOutput).toContain(
+ 'Test Suites: 1 passed, 1 total'
+ );
+
+ if (opts.checkE2E && runCypressTests()) {
+ const e2eResults = runCLI(`e2e ${appName}-e2e --no-watch`);
+ expect(e2eResults).toContain('All specs passed!');
+ expect(await killPorts()).toBeTruthy();
+ }
+}
diff --git a/e2e/react/tsconfig.json b/e2e/react-core/tsconfig.json
similarity index 100%
rename from e2e/react/tsconfig.json
rename to e2e/react-core/tsconfig.json
diff --git a/e2e/react/tsconfig.spec.json b/e2e/react-core/tsconfig.spec.json
similarity index 100%
rename from e2e/react/tsconfig.spec.json
rename to e2e/react-core/tsconfig.spec.json
diff --git a/e2e/react-extensions/jest.config.ts b/e2e/react-extensions/jest.config.ts
new file mode 100644
index 0000000000..bc7b24d4dd
--- /dev/null
+++ b/e2e/react-extensions/jest.config.ts
@@ -0,0 +1,11 @@
+/* eslint-disable */
+export default {
+ transform: {
+ '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
+ },
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
+ maxWorkers: 1,
+ globals: {},
+ displayName: 'e2e-react-extensions',
+ preset: '../../jest.preset.js',
+};
diff --git a/e2e/react-extensions/project.json b/e2e/react-extensions/project.json
new file mode 100644
index 0000000000..c2b16e9226
--- /dev/null
+++ b/e2e/react-extensions/project.json
@@ -0,0 +1,11 @@
+{
+ "name": "e2e-react-extensions",
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
+ "sourceRoot": "e2e/react-extensions",
+ "projectType": "application",
+ "targets": {
+ "e2e": {},
+ "run-e2e-tests": {}
+ },
+ "implicitDependencies": ["react"]
+}
diff --git a/e2e/react/src/cypress-component-tests.test.ts b/e2e/react-extensions/src/cypress-component-tests.test.ts
similarity index 100%
rename from e2e/react/src/cypress-component-tests.test.ts
rename to e2e/react-extensions/src/cypress-component-tests.test.ts
diff --git a/e2e/react-extensions/src/react-vite.test.ts b/e2e/react-extensions/src/react-vite.test.ts
new file mode 100644
index 0000000000..675251d715
--- /dev/null
+++ b/e2e/react-extensions/src/react-vite.test.ts
@@ -0,0 +1,140 @@
+import {
+ checkFilesExist,
+ cleanupProject,
+ newProject,
+ readJson,
+ runCLI,
+ runCLIAsync,
+ uniq,
+} from '@nrwl/e2e/utils';
+
+describe('Build React applications and libraries with Vite', () => {
+ let proj: string;
+
+ beforeEach(() => {
+ proj = newProject();
+ });
+
+ afterAll(() => {
+ cleanupProject();
+ });
+
+ it('should test and lint app with bundler=vite', async () => {
+ const viteApp = uniq('viteapp');
+
+ runCLI(
+ `generate @nrwl/react:app ${viteApp} --bundler=vite --unitTestRunner=vitest --no-interactive`
+ );
+
+ const appTestResults = await runCLIAsync(`test ${viteApp}`);
+ expect(appTestResults.combinedOutput).toContain(
+ 'Successfully ran target test'
+ );
+
+ const appLintResults = await runCLIAsync(`lint ${viteApp}`);
+ expect(appLintResults.combinedOutput).toContain(
+ 'Successfully ran target lint'
+ );
+
+ await runCLIAsync(`build ${viteApp}`);
+ checkFilesExist(`dist/apps/${viteApp}/index.html`);
+ }, 300_000);
+
+ it('should test and lint app with bundler=vite and inSourceTests', async () => {
+ const viteApp = uniq('viteapp');
+ const viteLib = uniq('vitelib');
+
+ runCLI(
+ `generate @nrwl/react:app ${viteApp} --bundler=vite --unitTestRunner=vitest --inSourceTests --no-interactive`
+ );
+ expect(() => {
+ checkFilesExist(`apps/${viteApp}/src/app/app.spec.tsx`);
+ }).toThrow();
+
+ const appTestResults = await runCLIAsync(`test ${viteApp}`);
+ expect(appTestResults.combinedOutput).toContain(
+ 'Successfully ran target test'
+ );
+
+ const appLintResults = await runCLIAsync(`lint ${viteApp}`);
+ expect(appLintResults.combinedOutput).toContain(
+ 'Successfully ran target lint'
+ );
+
+ await runCLIAsync(`build ${viteApp}`);
+ checkFilesExist(`dist/apps/${viteApp}/index.html`);
+
+ runCLI(
+ `generate @nrwl/react:lib ${viteLib} --bundler=vite --inSourceTests --unitTestRunner=vitest --no-interactive`
+ );
+ expect(() => {
+ checkFilesExist(`libs/${viteLib}/src/lib/${viteLib}.spec.tsx`);
+ }).toThrow();
+
+ runCLI(
+ `generate @nrwl/react:component comp1 --inSourceTests --export --project=${viteLib} --no-interactive`
+ );
+ expect(() => {
+ checkFilesExist(`libs/${viteLib}/src/lib/comp1/comp1.spec.tsx`);
+ }).toThrow();
+
+ runCLI(
+ `generate @nrwl/react:component comp2 --export --project=${viteLib} --no-interactive`
+ );
+ checkFilesExist(`libs/${viteLib}/src/lib/comp2/comp2.spec.tsx`);
+
+ const libTestResults = await runCLIAsync(`test ${viteLib}`);
+ expect(libTestResults.combinedOutput).toContain(
+ 'Successfully ran target test'
+ );
+
+ const libLintResults = await runCLIAsync(`lint ${viteLib}`);
+ expect(libLintResults.combinedOutput).toContain(
+ 'Successfully ran target lint'
+ );
+
+ await runCLIAsync(`build ${viteLib}`);
+ checkFilesExist(
+ `dist/libs/${viteLib}/index.d.ts`,
+ `dist/libs/${viteLib}/index.js`,
+ `dist/libs/${viteLib}/index.mjs`
+ );
+ }, 300_000);
+
+ it('should support bundling with Vite', async () => {
+ const viteLib = uniq('vitelib');
+
+ runCLI(
+ `generate @nrwl/react:lib ${viteLib} --bundler=vite --no-interactive --unit-test-runner=none`
+ );
+
+ const packageJson = readJson('package.json');
+ // Vite does not need these libraries to work.
+ expect(packageJson.dependencies['core-js']).toBeUndefined();
+ expect(packageJson.dependencies['tslib']).toBeUndefined();
+
+ await runCLIAsync(`build ${viteLib}`);
+
+ checkFilesExist(
+ `dist/libs/${viteLib}/package.json`,
+ `dist/libs/${viteLib}/index.d.ts`,
+ `dist/libs/${viteLib}/index.js`,
+ `dist/libs/${viteLib}/index.mjs`
+ );
+
+ // Convert non-buildable lib to buildable one
+ const nonBuildableLib = uniq('nonbuildablelib');
+ runCLI(
+ `generate @nrwl/react:lib ${nonBuildableLib} --no-interactive --unitTestRunner=jest`
+ );
+ runCLI(
+ `generate @nrwl/vite:configuration ${nonBuildableLib} --uiFramework=react --no-interactive`
+ );
+ await runCLIAsync(`build ${nonBuildableLib}`);
+ checkFilesExist(
+ `dist/libs/${nonBuildableLib}/index.d.ts`,
+ `dist/libs/${nonBuildableLib}/index.js`,
+ `dist/libs/${nonBuildableLib}/index.mjs`
+ );
+ }, 300_000);
+});
diff --git a/e2e/react-extensions/tsconfig.json b/e2e/react-extensions/tsconfig.json
new file mode 100644
index 0000000000..6d5abf8483
--- /dev/null
+++ b/e2e/react-extensions/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "types": ["node", "jest"]
+ },
+ "include": [],
+ "files": [],
+ "references": [
+ {
+ "path": "./tsconfig.spec.json"
+ }
+ ]
+}
diff --git a/e2e/react-extensions/tsconfig.spec.json b/e2e/react-extensions/tsconfig.spec.json
new file mode 100644
index 0000000000..1a24bfb0a1
--- /dev/null
+++ b/e2e/react-extensions/tsconfig.spec.json
@@ -0,0 +1,20 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../dist/out-tsc",
+ "module": "commonjs",
+ "types": ["jest", "node"]
+ },
+ "include": [
+ "**/*.test.ts",
+ "**/*.spec.ts",
+ "**/*.spec.tsx",
+ "**/*.test.tsx",
+ "**/*.spec.js",
+ "**/*.test.js",
+ "**/*.spec.jsx",
+ "**/*.test.jsx",
+ "**/*.d.ts",
+ "jest.config.ts"
+ ]
+}
diff --git a/e2e/react/src/react-misc.test.ts b/e2e/react/src/react-misc.test.ts
deleted file mode 100644
index 5d1b9ec07f..0000000000
--- a/e2e/react/src/react-misc.test.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import {
- checkFilesExist,
- newProject,
- runCLI,
- runCLIAsync,
- uniq,
-} from '@nrwl/e2e/utils';
-
-describe('React Applications: additional packages', () => {
- beforeAll(() => newProject());
-
- it('should generate app with routing', async () => {
- const appName = uniq('app');
-
- runCLI(
- `generate @nrwl/react:app ${appName} --routing --bundler=webpack --no-interactive`
- );
-
- runCLI(`build ${appName} --outputHashing none`);
-
- checkFilesExist(
- `dist/apps/${appName}/index.html`,
- `dist/apps/${appName}/runtime.js`,
- `dist/apps/${appName}/main.js`
- );
- }, 250_000);
-
- it('should be able to add a redux slice', async () => {
- const appName = uniq('app');
- const libName = uniq('lib');
-
- runCLI(`g @nrwl/react:app ${appName} --bundler=webpack --no-interactive`);
- runCLI(`g @nrwl/react:redux lemon --project=${appName}`);
- runCLI(
- `g @nrwl/react:lib ${libName} --unit-test-runner=jest --no-interactive`
- );
- runCLI(`g @nrwl/react:redux orange --project=${libName}`);
-
- const appTestResults = await runCLIAsync(`test ${appName}`);
- expect(appTestResults.combinedOutput).toContain(
- 'Test Suites: 2 passed, 2 total'
- );
-
- const libTestResults = await runCLIAsync(`test ${libName}`);
- expect(libTestResults.combinedOutput).toContain(
- 'Test Suites: 2 passed, 2 total'
- );
- }, 250_000);
-});