From 03848b25dbba29d92dea7ff759c7df8ba2cfc89c Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Thu, 29 Jun 2023 11:47:46 -0400 Subject: [PATCH] fix(remix): set up e2e so it runs out of the box --- .../generators/cypress/cypress.impl.spec.ts | 47 +++++++++++++++++++ .../src/generators/cypress/cypress.impl.ts | 40 ++++++++++++++-- .../remix/src/generators/cypress/schema.d.ts | 10 ++++ 3 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 packages/remix/src/generators/cypress/cypress.impl.spec.ts create mode 100644 packages/remix/src/generators/cypress/schema.d.ts diff --git a/packages/remix/src/generators/cypress/cypress.impl.spec.ts b/packages/remix/src/generators/cypress/cypress.impl.spec.ts new file mode 100644 index 000000000..ccd8b3ed1 --- /dev/null +++ b/packages/remix/src/generators/cypress/cypress.impl.spec.ts @@ -0,0 +1,47 @@ +import { readProjectConfiguration, Tree } from '@nx/devkit'; +import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; +import generator from './cypress.impl'; + +describe('Cypress generator', () => { + let tree: Tree; + + beforeEach(() => { + tree = createTreeWithEmptyWorkspace(); + }); + + it('should generate cypress project', async () => { + await generator(tree, { project: 'demo', name: 'demo-e2e' }); + + const config = readProjectConfiguration(tree, 'demo-e2e'); + expect(config.targets).toEqual({ + e2e: { + dependsOn: ['dev-server'], + executor: '@nx/cypress:cypress', + options: { + baseUrl: 'http://localhost:3000', + cypressConfig: 'demo-e2e/cypress.config.ts', + skipServe: true, + testingType: 'e2e', + }, + }, + lint: { + executor: '@nx/linter:eslint', + options: { + lintFilePatterns: ['demo-e2e/**/*.{js,ts}'], + }, + outputs: ['{options.outputFile}'], + }, + 'dev-server': { + command: 'nx serve demo', + configurations: { + production: { + command: 'nx serve demo --configuration=production', + }, + }, + options: { + readyWhen: 'Server started', + }, + }, + }); + }); +}); diff --git a/packages/remix/src/generators/cypress/cypress.impl.ts b/packages/remix/src/generators/cypress/cypress.impl.ts index 9ff998c96..f8d59d477 100644 --- a/packages/remix/src/generators/cypress/cypress.impl.ts +++ b/packages/remix/src/generators/cypress/cypress.impl.ts @@ -1,13 +1,20 @@ import { ensurePackage, + GeneratorCallback, joinPathFragments, readProjectConfiguration, Tree, + updateProjectConfiguration, } from '@nx/devkit'; import { version as nxVersion } from 'nx/package.json'; +import { CypressGeneratorSchema } from './schema'; -export default async function (tree: Tree, options: any) { +export default async function ( + tree: Tree, + options: CypressGeneratorSchema +): Promise { + options.baseUrl ??= 'http://localhost:3000'; const { cypressInitGenerator, cypressProjectGenerator } = ensurePackage( '@nx/cypress', nxVersion @@ -19,10 +26,12 @@ export default async function (tree: Tree, options: any) { standaloneConfig: true, }); - const config = readProjectConfiguration(tree, options.name); - tree.delete(joinPathFragments(config.sourceRoot, 'support', 'app.po.ts')); + const projectConfig = readProjectConfiguration(tree, options.name); + tree.delete( + joinPathFragments(projectConfig.sourceRoot, 'support', 'app.po.ts') + ); tree.write( - joinPathFragments(config.sourceRoot, 'e2e', 'app.cy.ts'), + joinPathFragments(projectConfig.sourceRoot, 'e2e', 'app.cy.ts'), `describe('webapp', () => { beforeEach(() => cy.visit('/')); @@ -33,7 +42,7 @@ export default async function (tree: Tree, options: any) { ); const supportFilePath = joinPathFragments( - config.sourceRoot, + projectConfig.sourceRoot, 'support', 'e2e.ts' ); @@ -58,6 +67,27 @@ Cypress.on("uncaught:exception", (err) => { });` ); + // run-commands won't emit { success: true, baseUrl: '...' } to Cypress executor. + // We'll wire it up manually and skip serve from Cypress. + projectConfig.targets.e2e.options.skipServe = true; + projectConfig.targets.e2e.options.baseUrl = + options.baseUrl ?? 'http://localhost:3000'; + projectConfig.targets.e2e.dependsOn = ['dev-server']; + delete projectConfig.targets.e2e.options.devServerTarget; + delete projectConfig.targets.e2e?.configurations?.production.devServerTarget; + projectConfig.targets['dev-server'] = { + command: `nx serve ${options.project}`, + options: { + readyWhen: 'Server started', + }, + configurations: { + production: { + command: `nx serve ${options.project} --configuration=production`, + }, + }, + }; + updateProjectConfiguration(tree, options.name, projectConfig); + // returning this in case the cypress generator has any side effects return async () => { await initSideEffects(); diff --git a/packages/remix/src/generators/cypress/schema.d.ts b/packages/remix/src/generators/cypress/schema.d.ts new file mode 100644 index 000000000..61a83a81c --- /dev/null +++ b/packages/remix/src/generators/cypress/schema.d.ts @@ -0,0 +1,10 @@ +export interface CypressGeneratorSchema { + project: string; + name: string; + baseUrl?: string; + directory?: string; + linter?: 'none' | 'eslint'; + js?: boolean; + skipFormat?: boolean; + setParserOptionsProject?: boolean; +}