diff --git a/e2e/schematics/cypress.test.ts b/e2e/schematics/cypress.test.ts index 25ba77de6f13b..2e9d35be4f6ea 100644 --- a/e2e/schematics/cypress.test.ts +++ b/e2e/schematics/cypress.test.ts @@ -4,7 +4,9 @@ import { newApp, newProject, readJson, - runCLI + runCLI, + updateFile, + readFile } from '../utils'; describe('Cypress E2E Test runner', () => { @@ -46,6 +48,19 @@ describe('Cypress E2E Test runner', () => { expect( runCLI('e2e --project=my-app-e2e --headless --watch=false') ).toContain('All specs passed!'); + + const originalContents = JSON.parse( + readFile('apps/my-app-e2e/cypress.json') + ); + delete originalContents.fixtures; + updateFile( + 'apps/my-app-e2e/cypress.json', + JSON.stringify(originalContents) + ); + + expect( + runCLI('e2e --project=my-app-e2e --headless --watch=false') + ).toContain('All specs passed!'); }, 1000000 ); diff --git a/packages/builders/src/cypress/cypress.builder.spec.ts b/packages/builders/src/cypress/cypress.builder.spec.ts index 1dd842ccd75aa..6faf2731e32a9 100644 --- a/packages/builders/src/cypress/cypress.builder.spec.ts +++ b/packages/builders/src/cypress/cypress.builder.spec.ts @@ -5,6 +5,7 @@ import { EventEmitter } from 'events'; import * as child_process from 'child_process'; import * as path from 'path'; import * as fsUtility from '@angular-devkit/schematics/tools/file-system-utility'; +import * as fsExtras from 'fs-extra'; const Cypress = require('cypress'); describe('Cypress builder', () => { @@ -178,5 +179,82 @@ describe('Cypress builder', () => { fakeEventEmitter.emit('exit'); // Passing tsc command }); + + it('should copy fixtures files to out-dir', () => { + spyOn(fsUtility, 'readFile').and.callFake((path: string) => { + return path.endsWith('tsconfig.e2e.json') + ? JSON.stringify({ + compilerOptions: { + outDir: '../../dist/out-tsc/apps/my-app-e2e/src' + } + }) + : JSON.stringify({ + fixtures: '../../dist/out-tsc/apps/my-app-e2e/src/fixtures' + }); + }); + const fakeEventEmitter = new EventEmitter(); + spyOn(child_process, 'fork').and.returnValue(fakeEventEmitter); + spyOn(Cypress, 'run'); + spyOn(fsExtras, 'copySync'); + + builder + .run({ + root: normalize('/root'), + projectType: 'application', + builder: '@nrwl/builders:cypress', + options: { + cypressConfig: 'apps/my-app-e2e/cypress.json', + tsConfig: 'apps/my-app-e2e/tsconfig.e2e.json', + devServerTarget: undefined, + headless: true, + baseUrl: undefined, + watch: false + } + }) + .subscribe(() => { + expect(fsExtras.copySync).toHaveBeenCalledWith( + 'apps/my-app-e2e/src/fixtures', + 'dist/out-tsc/my-app-e2e/src/fixtures' + ); + }); + + fakeEventEmitter.emit('exit'); // Passing tsc command + }); + + it('should copy not fixtures files if they are not defined in the cypress config', () => { + spyOn(fsUtility, 'readFile').and.callFake((path: string) => { + return path.endsWith('tsconfig.e2e.json') + ? JSON.stringify({ + compilerOptions: { + outDir: '../../dist/out-tsc/apps/my-app-e2e/src' + } + }) + : JSON.stringify({}); + }); + const fakeEventEmitter = new EventEmitter(); + spyOn(child_process, 'fork').and.returnValue(fakeEventEmitter); + spyOn(Cypress, 'run'); + spyOn(fsExtras, 'copySync'); + + builder + .run({ + root: normalize('/root'), + projectType: 'application', + builder: '@nrwl/builders:cypress', + options: { + cypressConfig: 'apps/my-app-e2e/cypress.json', + tsConfig: 'apps/my-app-e2e/tsconfig.e2e.json', + devServerTarget: undefined, + headless: true, + baseUrl: undefined, + watch: false + } + }) + .subscribe(() => { + expect(fsExtras.copySync).not.toHaveBeenCalled(); + }); + + fakeEventEmitter.emit('exit'); // Passing tsc command + }); }); }); diff --git a/packages/builders/src/cypress/cypress.builder.ts b/packages/builders/src/cypress/cypress.builder.ts index 0848710e43468..13082dd58122f 100644 --- a/packages/builders/src/cypress/cypress.builder.ts +++ b/packages/builders/src/cypress/cypress.builder.ts @@ -79,7 +79,9 @@ export default class CypressBuilder implements Builder { ); return this.compileTypescriptFiles(options.tsConfig, options.watch).pipe( - tap(() => this.copyCypressFixtures(options.tsConfig)), + tap(() => + this.copyCypressFixtures(options.tsConfig, options.cypressConfig) + ), concatMap( () => !options.baseUrl && options.devServerTarget @@ -147,14 +149,16 @@ export default class CypressBuilder implements Builder { * This is done because `tsc` doesn't handle `json` files. * @param tsConfigPath */ - private copyCypressFixtures(tsConfigPath: string) { - const tsconfigJson = JSON.parse(readFile(tsConfigPath)); + private copyCypressFixtures(tsConfigPath: string, cypressConfigPath: string) { + const cypressConfig = JSON.parse(readFile(cypressConfigPath)); + // DOn't copy fixtures if cypress config does not have it set + if (!cypressConfig.fixtures) { + return; + } + copySync( `${path.dirname(tsConfigPath)}/src/fixtures`, - `${path.resolve( - path.dirname(tsConfigPath), - tsconfigJson.compilerOptions.outDir - )}/fixtures`, + path.join(path.dirname(cypressConfigPath), cypressConfig.fixtures), { overwrite: true } ); }