nx/e2e/react-native/src/react-native.test.ts
Jack Hsu ec5a5e6360
feat(react): update app and lib generators to support new TS solution setup (#28808)
This PR updates app and lib generators in the following packages such
that they will generate files with the TS solution setup if it is
detected.

- `@nx/react`
- `@nx/next`
- `@nx/remix`
- `@nx/expo`
- `@nx/react-native`

React apps and libs will be linked using npm/pnpm/yarn/bun workspaces
feature rather than through tsconfig paths. This means that local
aliases like `@/` will work with Next.js and Remix apps.

Note: This will be behind `--workspaces` flag when using `npx
create-nx-workspace` and choosing React stack. If you use the None/TS
stack then adding plugins like `nx add @nx/react` then generating apps,
it will automatically pick up the new TS solution setup.


<!-- 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
React generators are not compatible with TS solution setup (i.e.
workspaces + TS project references).

## Expected Behavior
React generators work with new TS solution setup (Plain, Next.js, Remix,
Expo, React Native).

## Related Issue(s)
#28322

---------

Co-authored-by: Leosvel Pérez Espinosa <leosvel.perez.espinosa@gmail.com>
Co-authored-by: Nicholas Cunningham <ndcunningham@gmail.com>
2024-11-28 22:18:45 -05:00

142 lines
3.6 KiB
TypeScript

import { ChildProcess } from 'child_process';
import {
runCLI,
cleanupProject,
newProject,
uniq,
runCommandUntil,
killProcessAndPorts,
fileExists,
checkFilesExist,
runE2ETests,
} from 'e2e/utils';
describe('@nx/react-native', () => {
let appName: string;
beforeAll(() => {
newProject();
appName = uniq('app');
runCLI(
`generate @nx/react-native:app ${appName} --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
);
});
afterAll(() => cleanupProject());
it('should bundle the app', async () => {
expect(() =>
runCLI(
`bundle ${appName} --platform=ios --bundle-output=dist.js --entry-file=src/main.tsx`
)
).not.toThrow();
fileExists(` ${appName}/dist.js`);
}, 200_000);
it('should start the app', async () => {
let process: ChildProcess;
const port = 8081;
try {
process = await runCommandUntil(
`start ${appName} --no-interactive --port=${port}`,
(output) => {
return (
output.includes(`http://localhost:${port}`) ||
output.includes('Starting JS server...') ||
output.includes('Welcome to Metro')
);
}
);
} catch (err) {
console.error(err);
}
// port and process cleanup
if (process && process.pid) {
await killProcessAndPorts(process.pid, port);
}
});
it('should serve', async () => {
let process: ChildProcess;
const port = 8081;
try {
process = await runCommandUntil(
`serve ${appName} --port=${port}`,
(output) => {
return output.includes(`http://localhost:${port}`);
}
);
} catch (err) {
console.error(err);
}
// port and process cleanup
try {
if (process && process.pid) {
await killProcessAndPorts(process.pid, port);
}
} catch (err) {
expect(err).toBeFalsy();
}
});
it('should run e2e for cypress', async () => {
if (runE2ETests()) {
expect(() => runCLI(`e2e ${appName}-e2e`)).not.toThrow();
expect(() =>
runCLI(`e2e ${appName}-e2e --configuration=ci`)
).not.toThrow();
// port and process cleanup
try {
if (process && process.pid) {
await killProcessAndPorts(process.pid, 4200);
}
} catch (err) {
expect(err).toBeFalsy();
}
}
});
it('should create storybook with application', async () => {
runCLI(
`generate @nx/react:storybook-configuration ${appName} --generateStories --no-interactive`
);
checkFilesExist(
`${appName}/.storybook/main.ts`,
`${appName}/src/app/App.stories.tsx`
);
});
it('should run build with vite bundler and e2e with playwright', async () => {
const appName2 = uniq('my-app');
runCLI(
`generate @nx/react-native:application ${appName2} --directory=apps/${appName2} --bundler=vite --e2eTestRunner=playwright --install=false --no-interactive --unitTestRunner=jest --linter=eslint`
);
expect(() => runCLI(`build ${appName2}`)).not.toThrow();
if (runE2ETests()) {
expect(() => runCLI(`e2e ${appName2}-e2e`)).not.toThrow();
// port and process cleanup
try {
if (process && process.pid) {
await killProcessAndPorts(process.pid, 4200);
}
} catch (err) {
expect(err).toBeFalsy();
}
}
runCLI(
`generate @nx/react-native:storybook-configuration ${appName2} --generateStories --no-interactive`
);
checkFilesExist(
`apps/${appName2}/.storybook/main.ts`,
`apps/${appName2}/src/app/App.stories.tsx`
);
});
});