Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(testing): fix react CT w/ vite and dependant projects #16475

Merged
merged 1 commit into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 58 additions & 15 deletions e2e/react-extensions/src/cypress-component-tests.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ensureCypressInstallation,
newProject,
runCLI,
runCypressTests,
uniq,
updateFile,
updateJson,
Expand Down Expand Up @@ -146,18 +147,22 @@ export default Input;
runCLI(
`generate @nx/react:cypress-component-configuration --project=${appName} --generate-tests`
);
expect(runCLI(`component-test ${appName} --no-watch`)).toContain(
'All specs passed!'
);
if (runCypressTests()) {
expect(runCLI(`component-test ${appName} --no-watch`)).toContain(
'All specs passed!'
);
}
}, 300_000);

it('should successfully component test lib being used in app', () => {
runCLI(
`generate @nx/react:cypress-component-configuration --project=${usedInAppLibName} --generate-tests`
);
expect(runCLI(`component-test ${usedInAppLibName} --no-watch`)).toContain(
'All specs passed!'
);
if (runCypressTests()) {
expect(runCLI(`component-test ${usedInAppLibName} --no-watch`)).toContain(
'All specs passed!'
);
}
}, 300_000);

it('should test buildable lib not being used in app', () => {
Expand All @@ -184,9 +189,12 @@ describe(Input.name, () => {
runCLI(
`generate @nx/react:cypress-component-configuration --project=${buildableLibName} --generate-tests --build-target=${appName}:build`
);
expect(runCLI(`component-test ${buildableLibName} --no-watch`)).toContain(
'All specs passed!'
);

if (runCypressTests()) {
expect(runCLI(`component-test ${buildableLibName} --no-watch`)).toContain(
'All specs passed!'
);
}

// add tailwind
runCLI(`generate @nx/react:setup-tailwind --project=${buildableLibName}`);
Expand All @@ -213,9 +221,11 @@ ${content}`;
}
);

expect(runCLI(`component-test ${buildableLibName} --no-watch`)).toContain(
'All specs passed!'
);
if (runCypressTests()) {
expect(runCLI(`component-test ${buildableLibName} --no-watch`)).toContain(
'All specs passed!'
);
}
}, 300_000);

it('should work with async webpack config', () => {
Expand Down Expand Up @@ -250,8 +260,41 @@ ${content}`;
return config;
});

const results = runCLI(`component-test ${appName}`);
expect(results).toContain('I am from the custom async Webpack config');
expect(results).toContain('All specs passed!');
if (runCypressTests()) {
const results = runCLI(`component-test ${appName}`);
expect(results).toContain('I am from the custom async Webpack config');
expect(results).toContain('All specs passed!');
}
});

// flaky bc of upstream issue https://github.com/cypress-io/cypress/issues/25913
it.skip('should CT vite projects importing other projects', () => {
const viteLibName = uniq('vite-lib');
runCLI(
`generate @nrwl/react:lib ${viteLibName} --bundler=vite --no-interactive`
);

updateFile(`libs/${viteLibName}/src/lib/${viteLibName}.tsx`, () => {
return `import { Btn } from '@${projectName}/${usedInAppLibName}';

export function MyComponent() {
return (
<>
<Btn text={'I am the app'}/>
<p>hello</p>
</>
);
}
export default MyComponent;`;
});

runCLI(
`generate @nrwl/react:cypress-component-configuration --project=${viteLibName} --generate-tests --bundler=vite --build-target=${appName}:build`
);
if (runCypressTests()) {
expect(runCLI(`component-test ${viteLibName}`)).toContain(
'All specs passed!'
);
}
});
});
43 changes: 42 additions & 1 deletion packages/react/plugins/component-testing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import type { CypressExecutorOptions } from '@nx/cypress/src/executors/cypress/cypress.impl';
import {
ExecutorContext,
joinPathFragments,
logger,
parseTargetString,
ProjectGraph,
Expand All @@ -19,7 +20,8 @@ import {
getProjectConfigByPath,
} from '@nx/cypress/src/utils/ct-helpers';

import type { Configuration } from 'webpack';
import { existsSync, lstatSync } from 'fs';
import { dirname, join } from 'path';
type ViteDevServer = {
framework: 'react';
bundler: 'vite';
Expand Down Expand Up @@ -66,6 +68,36 @@ export function nxComponentTestingPreset(
specPattern: 'src/**/*.cy.{js,jsx,ts,tsx}',
devServer: {
...({ framework: 'react', bundler: 'vite' } as const),
viteConfig: async () => {
const normalizedPath = ['.ts', '.js'].some((ext) =>
pathToConfig.endsWith(ext)
)
? pathToConfig
: dirname(pathToConfig);
const viteConfigPath = findViteConfig(normalizedPath);

const { mergeConfig, loadConfigFromFile, searchForWorkspaceRoot } =
(await import('vite')) as typeof import('vite');

const resolved = await loadConfigFromFile(
{
mode: 'watch',
command: 'serve',
},
viteConfigPath
);
return mergeConfig(resolved.config, {
server: {
fs: {
allow: [
searchForWorkspaceRoot(normalizedPath),
workspaceRoot,
joinPathFragments(workspaceRoot, 'node_modules/vite'),
barbados-clemens marked this conversation as resolved.
Show resolved Hide resolved
],
},
},
});
},
},
};
}
Expand Down Expand Up @@ -232,3 +264,12 @@ function buildTargetWebpack(
};
}
}
function findViteConfig(projectRootFullPath: string): string {
const allowsExt = ['js', 'mjs', 'ts', 'cjs', 'mts', 'cts'];

for (const ext of allowsExt) {
if (existsSync(join(projectRootFullPath, `vite.config.${ext}`))) {
return join(projectRootFullPath, `vite.config.${ext}`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ export async function addFiles(
addDependenciesToPackageJson(tree, {}, { '@nx/webpack': nxVersion });
}

if (
options.bundler === 'vite' ||
(!options.bundler && actualBundler === 'vite')
) {
addDependenciesToPackageJson(tree, {}, { '@nx/vite': nxVersion });
}

if (options.generateTests) {
const filePaths = [];
visitNotIgnoredFiles(tree, projectConfig.sourceRoot, (filePath) => {
Expand Down
2 changes: 2 additions & 0 deletions scripts/depcheck/missing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ const IGNORE_MATCHES_IN_PACKAGE = {
'url-loader',
'webpack',
'webpack-merge',
// used via the CT react plugin installed via vite plugin
'vite',
],
'react-native': ['@nx/storybook'],
rollup: ['@swc/core'],
Expand Down