diff --git a/e2e/react-module-federation/src/react-module-federation.test.ts b/e2e/react-module-federation/src/react-module-federation.test.ts index c7138cb7528135..8ce1546c097fad 100644 --- a/e2e/react-module-federation/src/react-module-federation.test.ts +++ b/e2e/react-module-federation/src/react-module-federation.test.ts @@ -20,51 +20,61 @@ import { join } from 'path'; import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports'; describe('React Module Federation', () => { - let proj: string; - let tree: Tree; - beforeAll(() => { - tree = createTreeWithEmptyWorkspace(); - proj = newProject({ packages: ['@nx/react'] }); + newProject({ packages: ['@nx/react'] }); }); afterAll(() => cleanupProject()); describe('Default Configuration', () => { - it('should generate host and remote apps', async () => { - const shell = uniq('shell'); - const remote1 = uniq('remote1'); - const remote2 = uniq('remote2'); - const remote3 = uniq('remote3'); - - // Since we are using a single-file server for the remotes - const defaultRemotePort = 4201; - - runCLI( - `generate @nx/react:host ${shell} --remotes=${remote1},${remote2},${remote3} --style=css --no-interactive --skipFormat` - ); + it.each` + js + ${false} + ${true} + `( + 'should generate host and remote apps', + async ({ js }) => { + const shell = uniq('shell'); + const remote1 = uniq('remote1'); + const remote2 = uniq('remote2'); + const remote3 = uniq('remote3'); + + // Since we are using a single-file server for the remotes + const defaultRemotePort = 4201; + + runCLI( + `generate @nx/react:host ${shell} --remotes=${remote1},${remote2},${remote3} --style=css --no-interactive --skipFormat --js=${js}` + ); - checkFilesExist(`apps/${shell}/module-federation.config.ts`); - checkFilesExist(`apps/${remote1}/module-federation.config.ts`); - checkFilesExist(`apps/${remote2}/module-federation.config.ts`); - checkFilesExist(`apps/${remote3}/module-federation.config.ts`); + checkFilesExist( + `apps/${shell}/module-federation.config.${js ? 'js' : 'ts'}` + ); + checkFilesExist( + `apps/${remote1}/module-federation.config.${js ? 'js' : 'ts'}` + ); + checkFilesExist( + `apps/${remote2}/module-federation.config.${js ? 'js' : 'ts'}` + ); + checkFilesExist( + `apps/${remote3}/module-federation.config.${js ? 'js' : 'ts'}` + ); - await expect(runCLIAsync(`test ${shell}`)).resolves.toMatchObject({ - combinedOutput: expect.stringContaining( - 'Test Suites: 1 passed, 1 total' - ), - }); + await expect(runCLIAsync(`test ${shell}`)).resolves.toMatchObject({ + combinedOutput: expect.stringContaining( + 'Test Suites: 1 passed, 1 total' + ), + }); - updateFile( - `apps/${shell}/webpack.config.ts`, - stripIndents` - import { composePlugins, withNx, ModuleFederationConfig } from '@nx/webpack'; - import { withReact } from '@nx/react'; - import { withModuleFederation } from '@nx/react/module-federation'; + updateFile( + `apps/${shell}/webpack.config.${js ? 'js' : 'ts'}`, + stripIndents` + const { composePlugins, withNx } = require('@nx/webpack'); + const { withReact } = require('@nx/react'); + const { withModuleFederation } = require('@nx/react/module-federation'); - import baseConfig from './module-federation.config'; + const baseConfig = require('./module-federation.config'); - const config: ModuleFederationConfig = { + const config = { ...baseConfig, remotes: [ '${remote1}', @@ -76,11 +86,11 @@ describe('React Module Federation', () => { // Nx plugins for webpack to build config object from Nx options and context. module.exports = composePlugins(withNx(), withReact(), withModuleFederation(config)); ` - ); + ); - updateFile( - `apps/${shell}-e2e/src/integration/app.spec.ts`, - stripIndents` + updateFile( + `apps/${shell}-e2e/src/integration/app.spec.${js ? 'js' : 'ts'}`, + stripIndents` import { getGreeting } from '../support/app.po'; describe('shell app', () => { @@ -105,34 +115,36 @@ describe('React Module Federation', () => { }); }); ` - ); - - if (runE2ETests()) { - const e2eResultsSwc = await runCommandUntil( - `e2e ${shell}-e2e --no-watch --verbose`, - (output) => output.includes('All specs passed!') ); - await killProcessAndPorts( - e2eResultsSwc.pid, - readPort(shell), - defaultRemotePort - ); + if (runE2ETests()) { + const e2eResultsSwc = await runCommandUntil( + `e2e ${shell}-e2e --no-watch --verbose`, + (output) => output.includes('All specs passed!') + ); - const e2eResultsTsNode = await runCommandUntil( - `e2e ${shell}-e2e --no-watch --verbose`, - (output) => output.includes('All specs passed!'), - { - env: { NX_PREFER_TS_NODE: 'true' }, - } - ); - await killProcessAndPorts( - e2eResultsTsNode.pid, - readPort(shell), - defaultRemotePort - ); - } - }, 500_000); + await killProcessAndPorts( + e2eResultsSwc.pid, + readPort(shell), + defaultRemotePort + ); + + const e2eResultsTsNode = await runCommandUntil( + `e2e ${shell}-e2e --no-watch --verbose`, + (output) => output.includes('All specs passed!'), + { + env: { NX_PREFER_TS_NODE: 'true' }, + } + ); + await killProcessAndPorts( + e2eResultsTsNode.pid, + readPort(shell), + defaultRemotePort + ); + } + }, + 500_000 + ); it('should generate host and remote apps with ssr', async () => { const shell = uniq('shell'); @@ -861,8 +873,7 @@ describe('React Module Federation', () => { describe('Dynamic Module Federation', () => { beforeAll(() => { - tree = createTreeWithEmptyWorkspace(); - proj = newProject({ packages: ['@nx/react'] }); + newProject({ packages: ['@nx/react'] }); }); afterAll(() => cleanupProject()); diff --git a/packages/cypress/plugins/cypress-preset.ts b/packages/cypress/plugins/cypress-preset.ts index 54fc3a61e7363d..e2abfaf376e55f 100644 --- a/packages/cypress/plugins/cypress-preset.ts +++ b/packages/cypress/plugins/cypress-preset.ts @@ -1,6 +1,6 @@ import { workspaceRoot } from '@nx/devkit'; import { dirname, join, relative } from 'path'; -import { lstatSync } from 'fs'; +import { existsSync, lstatSync } from 'fs'; import vitePreprocessor from '../src/plugins/preprocessor-vite'; import { NX_PLUGIN_OPTIONS } from '../src/utils/symbols'; @@ -96,12 +96,22 @@ export function nxE2EPreset( ) { const basePath = options?.cypressDir || 'src'; + const dir = dirname(pathToConfig); + let supportFile: undefined | string = undefined; + for (const f of ['e2e.ts', 'e2e.js']) { + const candidate = join(dir, basePath, 'support', f); + if (existsSync(candidate)) { + supportFile = candidate; + break; + } + } + const baseConfig: any /*Cypress.EndToEndConfigOptions & { [NX_PLUGIN_OPTIONS]: unknown; }*/ = { ...nxBaseCypressPreset(pathToConfig), fileServerFolder: '.', - supportFile: `${basePath}/support/e2e.ts`, + supportFile, specPattern: `${basePath}/**/*.cy.{js,jsx,ts,tsx}`, fixturesFolder: `${basePath}/fixtures`, diff --git a/packages/cypress/src/generators/configuration/configuration.ts b/packages/cypress/src/generators/configuration/configuration.ts index d0b89ad0f1150d..274f052f676f29 100644 --- a/packages/cypress/src/generators/configuration/configuration.ts +++ b/packages/cypress/src/generators/configuration/configuration.ts @@ -264,7 +264,11 @@ function addTarget(tree: Tree, opts: NormalizedSchema) { options: { cypressConfig: joinPathFragments( projectConfig.root, - cyVersion && cyVersion < 10 ? 'cypress.json' : 'cypress.config.ts' + cyVersion && cyVersion < 10 + ? 'cypress.json' + : opts.js + ? 'cypress.config.js' + : 'cypress.config.ts' ), testingType: 'e2e', }, diff --git a/packages/react/src/generators/host/host.ts b/packages/react/src/generators/host/host.ts index 61142d20bbe8f4..b5f04f9cac5a33 100644 --- a/packages/react/src/generators/host/host.ts +++ b/packages/react/src/generators/host/host.ts @@ -72,6 +72,7 @@ export async function hostGeneratorInternal( skipFormat: true, projectNameAndRootFormat: options.projectNameAndRootFormat, typescriptConfiguration: options.typescriptConfiguration, + js: options.js, dynamic: options.dynamic, host: options.name, }); diff --git a/packages/react/src/generators/host/lib/add-module-federation-files.ts b/packages/react/src/generators/host/lib/add-module-federation-files.ts index 72636636e4934c..489de5313e6c56 100644 --- a/packages/react/src/generators/host/lib/add-module-federation-files.ts +++ b/packages/react/src/generators/host/lib/add-module-federation-files.ts @@ -55,9 +55,10 @@ export function addModuleFederationFiles( templateVariables ); - const pathToModuleFederationFiles = options.typescriptConfiguration - ? 'module-federation-ts' - : 'module-federation'; + const pathToModuleFederationFiles = + options.typescriptConfiguration && !options.js + ? 'module-federation-ts' + : 'module-federation'; // New entry file is created here. generateFiles( host, diff --git a/packages/react/src/generators/remote/remote.ts b/packages/react/src/generators/remote/remote.ts index 19182d516d4709..ebaaf9b1e69d76 100644 --- a/packages/react/src/generators/remote/remote.ts +++ b/packages/react/src/generators/remote/remote.ts @@ -39,9 +39,10 @@ export function addModuleFederationFiles( templateVariables ); - const pathToModuleFederationFiles = options.typescriptConfiguration - ? 'module-federation-ts' - : 'module-federation'; + const pathToModuleFederationFiles = + options.typescriptConfiguration && !options.js + ? 'module-federation-ts' + : 'module-federation'; generateFiles( host, @@ -49,23 +50,6 @@ export function addModuleFederationFiles( options.appProjectRoot, templateVariables ); - - if (options.typescriptConfiguration) { - const pathToWebpackConfig = joinPathFragments( - options.appProjectRoot, - 'webpack.config.js' - ); - const pathToWebpackProdConfig = joinPathFragments( - options.appProjectRoot, - 'webpack.config.prod.js' - ); - if (host.exists(pathToWebpackConfig)) { - host.delete(pathToWebpackConfig); - } - if (host.exists(pathToWebpackProdConfig)) { - host.delete(pathToWebpackProdConfig); - } - } } export async function remoteGenerator(host: Tree, schema: Schema) { diff --git a/packages/react/src/rules/update-module-federation-project.ts b/packages/react/src/rules/update-module-federation-project.ts index 2f95c03af8e076..7257dd0801c5be 100644 --- a/packages/react/src/rules/update-module-federation-project.ts +++ b/packages/react/src/rules/update-module-federation-project.ts @@ -25,14 +25,14 @@ export function updateModuleFederationProject( ...projectConfig.targets.build.options, main: `${options.appProjectRoot}/src/main.${options.js ? 'js' : 'ts'}`, webpackConfig: `${options.appProjectRoot}/webpack.config.${ - options.typescriptConfiguration ? 'ts' : 'js' + options.typescriptConfiguration && !options.js ? 'ts' : 'js' }`, }; projectConfig.targets.build.configurations.production = { ...projectConfig.targets.build.configurations.production, webpackConfig: `${options.appProjectRoot}/webpack.config.prod.${ - options.typescriptConfiguration ? 'ts' : 'js' + options.typescriptConfiguration && !options.js ? 'ts' : 'js' }`, }; @@ -40,7 +40,9 @@ export function updateModuleFederationProject( if (options.dynamic) { const pathToProdWebpackConfig = joinPathFragments( projectConfig.root, - `webpack.prod.config.${options.typescriptConfiguration ? 'ts' : 'js'}` + `webpack.prod.config.${ + options.typescriptConfiguration && !options.js ? 'ts' : 'js' + }` ); if (host.exists(pathToProdWebpackConfig)) { host.delete(pathToProdWebpackConfig);