import { cleanupProject, killPorts, newProject, runCLI, checkFilesExist, readJson, uniq, updateFile, runCommandAsync, listFiles, } from '@nx/e2e/utils'; describe('Remix E2E Tests', () => { describe('--integrated', () => { let proj: string; beforeAll(() => { proj = newProject({ packages: ['@nx/remix', '@nx/react'] }); }); afterAll(() => { killPorts(); cleanupProject(); }); it('should create app', async () => { const plugin = uniq('remix'); runCLI(`generate @nx/remix:app ${plugin}`); const buildResult = runCLI(`build ${plugin}`); expect(buildResult).toContain('Successfully ran target build'); const testResult = runCLI(`test ${plugin}`); expect(testResult).toContain('Successfully ran target test'); }, 120000); describe('--directory', () => { it('should create src in the specified directory --projectNameAndRootFormat=derived', async () => { const plugin = uniq('remix'); const appName = `sub-${plugin}`; runCLI( `generate @nx/remix:app ${plugin} --directory=sub --projectNameAndRootFormat=derived --rootProject=false --no-interactive` ); const result = runCLI(`build ${appName}`); expect(result).toContain('Successfully ran target build'); // TODO(colum): uncomment line below when fixed checkFilesExist(`apps/sub/${plugin}/build/index.js`); }, 120000); it('should create src in the specified directory --projectNameAndRootFormat=as-provided', async () => { const plugin = uniq('remix'); runCLI( `generate @nx/remix:app ${plugin} --directory=subdir --projectNameAndRootFormat=as-provided --rootProject=false --no-interactive` ); const result = runCLI(`build ${plugin}`); expect(result).toContain('Successfully ran target build'); checkFilesExist(`subdir/build/index.js`); }, 120000); }); describe('--tags', () => { it('should add tags to the project', async () => { const plugin = uniq('remix'); runCLI(`generate @nx/remix:app ${plugin} --tags e2etag,e2ePackage`); const project = readJson(`apps/${plugin}/project.json`); expect(project.tags).toEqual(['e2etag', 'e2ePackage']); }, 120000); }); describe('--js', () => { it('should create js app and build correctly', async () => { const plugin = uniq('remix'); runCLI(`generate @nx/remix:app ${plugin} --js=true`); const result = runCLI(`build ${plugin}`); expect(result).toContain('Successfully ran target build'); }, 120000); }); describe('--unitTestRunner', () => { it('should generate a library with vitest and test correctly', async () => { const plugin = uniq('remix'); runCLI(`generate @nx/remix:library ${plugin} --unitTestRunner=vitest`); const result = runCLI(`test ${plugin}`); expect(result).toContain(`Successfully ran target test`); }, 120_000); it('should generate a library with jest and test correctly', async () => { const reactapp = uniq('react'); runCLI( `generate @nx/react:application ${reactapp} --unitTestRunner=jest` ); const plugin = uniq('remix'); runCLI( `generate @nx/remix:application ${plugin} --unitTestRunner=jest` ); const result = runCLI(`test ${plugin}`); expect(result).toContain(`Successfully ran target test`); const reactResult = runCLI(`test ${reactapp}`); expect(reactResult).toContain(`Successfully ran target test`); }, 120_000); }); describe('error checking', () => { const plugin = uniq('remix'); beforeAll(async () => { runCLI(`generate @nx/remix:app ${plugin} --tags e2etag,e2ePackage`); }, 120000); it('should check for un-escaped dollar signs in routes', async () => { await expect(async () => runCLI( `generate @nx/remix:route --project ${plugin} --path my.route.$withParams.tsx` ) ).rejects.toThrow(); runCLI( `generate @nx/remix:route --project ${plugin} --path my.route.\\$withParams.tsx` ); expect(() => checkFilesExist(`apps/${plugin}/app/routes/my.route.$withParams.tsx`) ).not.toThrow(); }, 120000); it('should pass un-escaped dollar signs in routes with skipChecks flag', async () => { await runCommandAsync( `someWeirdUseCase=route-segment && yarn nx generate @nx/remix:route --project ${plugin} --path my.route.$someWeirdUseCase.tsx --force` ); expect(() => checkFilesExist( `apps/${plugin}/app/routes/my.route.route-segment.tsx` ) ).not.toThrow(); }, 120000); it('should check for un-escaped dollar signs in resource routes', async () => { await expect(async () => runCLI( `generate @nx/remix:resource-route --project ${plugin} --path my.route.$withParams.ts` ) ).rejects.toThrow(); runCLI( `generate @nx/remix:resource-route --project ${plugin} --path my.route.\\$withParams.ts` ); expect(() => checkFilesExist(`apps/${plugin}/app/routes/my.route.$withParams.ts`) ).not.toThrow(); }, 120000); xit('should pass un-escaped dollar signs in resource routes with skipChecks flag', async () => { await runCommandAsync( `someWeirdUseCase=route-segment && yarn nx generate @nx/remix:resource-route --project ${plugin} --path my.route.$someWeirdUseCase.ts --force` ); expect(() => checkFilesExist(`apps/${plugin}/app/routes/my.route.route-segment.ts`) ).not.toThrow(); }, 120000); }); }); describe('--standalone', () => { let proj: string; beforeAll(() => { proj = newProject({ packages: ['@nx/remix'] }); }); afterAll(() => { killPorts(); cleanupProject(); }); it('should create a standalone remix app', async () => { const appName = uniq('remix'); runCLI(`generate @nx/remix:preset --name ${appName} --verbose`); // Can import using ~ alias like a normal Remix setup. updateFile(`app/foo.ts`, `export const foo = 'foo';`); updateFile( `app/routes/index.tsx`, ` import { foo } from '~/foo'; export default function Index() { return (