diff options
Diffstat (limited to 'remote/test/puppeteer/packages/ng-schematics/test/src')
4 files changed, 548 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/ng-schematics/test/src/config.test.ts b/remote/test/puppeteer/packages/ng-schematics/test/src/config.test.ts new file mode 100644 index 0000000000..e4ec03ed54 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/test/src/config.test.ts @@ -0,0 +1,30 @@ +import {describe, it} from 'node:test'; + +import expect from 'expect'; + +import { + buildTestingTree, + getMultiApplicationFile, + setupHttpHooks, +} from './utils.js'; + +void describe('@puppeteer/ng-schematics: config', () => { + setupHttpHooks(); + + void describe('Single Project', () => { + void it('should create default file', async () => { + const tree = await buildTestingTree('config', 'single'); + expect(tree.files).toContain('/.puppeteerrc.mjs'); + }); + }); + + void describe('Multi projects', () => { + void it('should create default file', async () => { + const tree = await buildTestingTree('config', 'multi'); + expect(tree.files).toContain('/.puppeteerrc.mjs'); + expect(tree.files).not.toContain( + getMultiApplicationFile('.puppeteerrc.mjs') + ); + }); + }); +}); diff --git a/remote/test/puppeteer/packages/ng-schematics/test/src/e2e.test.ts b/remote/test/puppeteer/packages/ng-schematics/test/src/e2e.test.ts new file mode 100644 index 0000000000..8ae211cd59 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/test/src/e2e.test.ts @@ -0,0 +1,111 @@ +import {describe, it} from 'node:test'; + +import expect from 'expect'; + +import { + buildTestingTree, + getMultiApplicationFile, + setupHttpHooks, +} from './utils.js'; + +void describe('@puppeteer/ng-schematics: e2e', () => { + setupHttpHooks(); + + void describe('Single Project', () => { + void it('should create default file', async () => { + const tree = await buildTestingTree('e2e', 'single', { + name: 'myTest', + }); + expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.files).not.toContain('/e2e/tests/my-test.test.ts'); + }); + + void it('should create Node file', async () => { + const tree = await buildTestingTree('e2e', 'single', { + name: 'myTest', + testRunner: 'node', + }); + expect(tree.files).not.toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/my-test.test.ts'); + }); + + void it('should create file with route', async () => { + const route = 'home'; + const tree = await buildTestingTree('e2e', 'single', { + name: 'myTest', + route, + }); + expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain( + `setupBrowserHooks('${route}');` + ); + }); + + void it('should create with route with starting slash', async () => { + const route = '/home'; + const tree = await buildTestingTree('e2e', 'single', { + name: 'myTest', + route, + }); + expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); + expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain( + `setupBrowserHooks('home');` + ); + }); + }); + + void describe('Multi projects', () => { + void it('should create default file', async () => { + const tree = await buildTestingTree('e2e', 'multi', { + name: 'myTest', + }); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/my-test.e2e.ts') + ); + expect(tree.files).not.toContain( + getMultiApplicationFile('e2e/tests/my-test.test.ts') + ); + }); + + void it('should create Node file', async () => { + const tree = await buildTestingTree('e2e', 'multi', { + name: 'myTest', + testRunner: 'node', + }); + expect(tree.files).not.toContain( + getMultiApplicationFile('e2e/tests/my-test.e2e.ts') + ); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/my-test.test.ts') + ); + }); + + void it('should create file with route', async () => { + const route = 'home'; + const tree = await buildTestingTree('e2e', 'multi', { + name: 'myTest', + route, + }); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/my-test.e2e.ts') + ); + expect( + tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts')) + ).toContain(`setupBrowserHooks('${route}');`); + }); + + void it('should create with route with starting slash', async () => { + const route = '/home'; + const tree = await buildTestingTree('e2e', 'multi', { + name: 'myTest', + route, + }); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/my-test.e2e.ts') + ); + expect( + tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts')) + ).toContain(`setupBrowserHooks('home');`); + }); + }); +}); diff --git a/remote/test/puppeteer/packages/ng-schematics/test/src/ng-add.test.ts b/remote/test/puppeteer/packages/ng-schematics/test/src/ng-add.test.ts new file mode 100644 index 0000000000..d912c5dc3d --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/test/src/ng-add.test.ts @@ -0,0 +1,260 @@ +import {describe, it} from 'node:test'; + +import expect from 'expect'; + +import { + MULTI_LIBRARY_OPTIONS, + buildTestingTree, + getAngularJsonScripts, + getMultiApplicationFile, + getMultiLibraryFile, + getPackageJson, + runSchematic, + setupHttpHooks, +} from './utils.js'; + +void describe('@puppeteer/ng-schematics: ng-add', () => { + setupHttpHooks(); + + void describe('Single Project', () => { + void it('should create base files and update to "package.json"', async () => { + const tree = await buildTestingTree('ng-add'); + const {devDependencies, scripts} = getPackageJson(tree); + const {builder, configurations} = getAngularJsonScripts(tree); + + expect(tree.files).toContain('/e2e/tsconfig.json'); + expect(tree.files).toContain('/e2e/tests/app.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/utils.ts'); + expect(devDependencies).toContain('puppeteer'); + expect(scripts['e2e']).toBe('ng e2e'); + expect(builder).toBe('@puppeteer/ng-schematics:puppeteer'); + expect(configurations).toEqual({ + production: { + devServerTarget: 'sandbox:serve:production', + }, + }); + }); + void it('should update create proper "ng" command for non default tester', async () => { + let tree = await buildTestingTree('ng-add', 'single'); + // Re-run schematic to have e2e populated + tree = await runSchematic(tree, 'ng-add'); + const {scripts} = getPackageJson(tree); + const {builder} = getAngularJsonScripts(tree, false); + + expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer'); + expect(builder).toBe('@puppeteer/ng-schematics:puppeteer'); + }); + void it('should not create Puppeteer config', async () => { + const {files} = await buildTestingTree('ng-add', 'single'); + + expect(files).not.toContain('/.puppeteerrc.cjs'); + }); + void it('should create Jasmine files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'single', { + testRunner: 'jasmine', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain('/e2e/jasmine.json'); + expect(devDependencies).toContain('jasmine'); + expect(options['testRunner']).toBe('jasmine'); + }); + void it('should create Jest files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'single', { + testRunner: 'jest', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain('/e2e/jest.config.js'); + expect(devDependencies).toContain('jest'); + expect(devDependencies).toContain('@types/jest'); + expect(options['testRunner']).toBe('jest'); + }); + void it('should create Mocha files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'single', { + testRunner: 'mocha', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain('/e2e/.mocharc.js'); + expect(devDependencies).toContain('mocha'); + expect(devDependencies).toContain('@types/mocha'); + expect(options['testRunner']).toBe('mocha'); + }); + void it('should create Node files', async () => { + const tree = await buildTestingTree('ng-add', 'single', { + testRunner: 'node', + }); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain('/e2e/.gitignore'); + expect(tree.files).not.toContain('/e2e/tests/app.e2e.ts'); + expect(tree.files).toContain('/e2e/tests/app.test.ts'); + expect(options['testRunner']).toBe('node'); + }); + void it('should create TypeScript files', async () => { + const tree = await buildTestingTree('ng-add', 'single'); + const tsConfigPath = '/e2e/tsconfig.json'; + const tsConfig = tree.readJson(tsConfigPath); + + expect(tree.files).toContain(tsConfigPath); + expect(tsConfig).toMatchObject({ + extends: '../tsconfig.json', + compilerOptions: { + module: 'CommonJS', + }, + }); + }); + void it('should not create port value', async () => { + const tree = await buildTestingTree('ng-add'); + + const {options} = getAngularJsonScripts(tree); + expect(options['port']).toBeUndefined(); + }); + }); + + void describe('Multi projects Application', () => { + void it('should create base files and update to "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'multi'); + const {devDependencies, scripts} = getPackageJson(tree); + const {builder, configurations} = getAngularJsonScripts(tree); + + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tsconfig.json') + ); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/app.e2e.ts') + ); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/utils.ts') + ); + expect(devDependencies).toContain('puppeteer'); + expect(scripts['e2e']).toBe('ng e2e'); + expect(builder).toBe('@puppeteer/ng-schematics:puppeteer'); + expect(configurations).toEqual({ + production: { + devServerTarget: 'sandbox:serve:production', + }, + }); + }); + void it('should update create proper "ng" command for non default tester', async () => { + let tree = await buildTestingTree('ng-add', 'multi'); + // Re-run schematic to have e2e populated + tree = await runSchematic(tree, 'ng-add'); + const {scripts} = getPackageJson(tree); + const {builder} = getAngularJsonScripts(tree, false); + + expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer'); + expect(builder).toBe('@puppeteer/ng-schematics:puppeteer'); + }); + void it('should not create Puppeteer config', async () => { + const {files} = await buildTestingTree('ng-add', 'multi'); + + expect(files).not.toContain(getMultiApplicationFile('.puppeteerrc.cjs')); + expect(files).not.toContain('/.puppeteerrc.cjs'); + }); + void it('should create Jasmine files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'multi', { + testRunner: 'jasmine', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain(getMultiApplicationFile('e2e/jasmine.json')); + expect(devDependencies).toContain('jasmine'); + expect(options['testRunner']).toBe('jasmine'); + }); + void it('should create Jest files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'multi', { + testRunner: 'jest', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain( + getMultiApplicationFile('e2e/jest.config.js') + ); + expect(devDependencies).toContain('jest'); + expect(devDependencies).toContain('@types/jest'); + expect(options['testRunner']).toBe('jest'); + }); + void it('should create Mocha files and update "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'multi', { + testRunner: 'mocha', + }); + const {devDependencies} = getPackageJson(tree); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain(getMultiApplicationFile('e2e/.mocharc.js')); + expect(devDependencies).toContain('mocha'); + expect(devDependencies).toContain('@types/mocha'); + expect(options['testRunner']).toBe('mocha'); + }); + void it('should create Node files', async () => { + const tree = await buildTestingTree('ng-add', 'multi', { + testRunner: 'node', + }); + const {options} = getAngularJsonScripts(tree); + + expect(tree.files).toContain(getMultiApplicationFile('e2e/.gitignore')); + expect(tree.files).not.toContain( + getMultiApplicationFile('e2e/tests/app.e2e.ts') + ); + expect(tree.files).toContain( + getMultiApplicationFile('e2e/tests/app.test.ts') + ); + expect(options['testRunner']).toBe('node'); + }); + void it('should create TypeScript files', async () => { + const tree = await buildTestingTree('ng-add', 'multi'); + const tsConfigPath = getMultiApplicationFile('e2e/tsconfig.json'); + const tsConfig = tree.readJson(tsConfigPath); + + expect(tree.files).toContain(tsConfigPath); + expect(tsConfig).toMatchObject({ + extends: '../../../tsconfig.json', + compilerOptions: { + module: 'CommonJS', + }, + }); + }); + void it('should not create port value', async () => { + const tree = await buildTestingTree('ng-add'); + + const {options} = getAngularJsonScripts(tree); + expect(options['port']).toBeUndefined(); + }); + }); + + void describe('Multi projects Library', () => { + void it('should create base files and update to "package.json"', async () => { + const tree = await buildTestingTree('ng-add', 'multi'); + const config = getAngularJsonScripts( + tree, + true, + MULTI_LIBRARY_OPTIONS.name + ); + + expect(tree.files).not.toContain( + getMultiLibraryFile('e2e/tsconfig.json') + ); + expect(tree.files).not.toContain( + getMultiLibraryFile('e2e/tests/app.e2e.ts') + ); + expect(tree.files).not.toContain( + getMultiLibraryFile('e2e/tests/utils.ts') + ); + expect(config).toBeUndefined(); + }); + + void it('should not create Puppeteer config', async () => { + const {files} = await buildTestingTree('ng-add', 'multi'); + + expect(files).not.toContain(getMultiLibraryFile('.puppeteerrc.cjs')); + expect(files).not.toContain('/.puppeteerrc.cjs'); + }); + }); +}); diff --git a/remote/test/puppeteer/packages/ng-schematics/test/src/utils.ts b/remote/test/puppeteer/packages/ng-schematics/test/src/utils.ts new file mode 100644 index 0000000000..503cbd5cec --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/test/src/utils.ts @@ -0,0 +1,147 @@ +import https from 'https'; +import {before, after} from 'node:test'; +import {join} from 'path'; + +import type {JsonObject} from '@angular-devkit/core'; +import { + SchematicTestRunner, + type UnitTestTree, +} from '@angular-devkit/schematics/testing'; +import sinon from 'sinon'; + +const WORKSPACE_OPTIONS = { + name: 'workspace', + newProjectRoot: 'projects', + version: '14.0.0', +}; + +const SINGLE_APPLICATION_OPTIONS = { + name: 'sandbox', + directory: '.', + createApplication: true, + version: '14.0.0', +}; + +const MULTI_APPLICATION_OPTIONS = { + name: SINGLE_APPLICATION_OPTIONS.name, +}; + +export const MULTI_LIBRARY_OPTIONS = { + name: 'components', +}; + +export function setupHttpHooks(): void { + // Stop outgoing Request for version fetching + before(() => { + const httpsGetStub = sinon.stub(https, 'get'); + httpsGetStub.returns({ + on: (_: string, callback: () => void) => { + callback(); + }, + } as any); + }); + + after(() => { + sinon.restore(); + }); +} + +export function getAngularJsonScripts( + tree: UnitTestTree, + isDefault = true, + name = SINGLE_APPLICATION_OPTIONS.name +): { + builder: string; + configurations: Record<string, any>; + options: Record<string, any>; +} { + const angularJson = tree.readJson('angular.json') as any; + const e2eScript = isDefault ? 'e2e' : 'puppeteer'; + return angularJson['projects']?.[name]?.['architect'][e2eScript]; +} + +export function getPackageJson(tree: UnitTestTree): { + scripts: Record<string, string>; + devDependencies: string[]; +} { + const packageJson = tree.readJson('package.json') as JsonObject; + return { + scripts: packageJson['scripts'] as any, + devDependencies: Object.keys( + packageJson['devDependencies'] as Record<string, string> + ), + }; +} + +export function getMultiApplicationFile(file: string): string { + return `/${WORKSPACE_OPTIONS.newProjectRoot}/${MULTI_APPLICATION_OPTIONS.name}/${file}`; +} +export function getMultiLibraryFile(file: string): string { + return `/${WORKSPACE_OPTIONS.newProjectRoot}/${MULTI_LIBRARY_OPTIONS.name}/${file}`; +} + +export async function buildTestingTree( + command: 'ng-add' | 'e2e' | 'config', + type: 'single' | 'multi' = 'single', + userOptions?: Record<string, unknown> +): Promise<UnitTestTree> { + const runner = new SchematicTestRunner( + 'schematics', + join(__dirname, '../../lib/schematics/collection.json') + ); + const options = { + testRunner: 'jasmine', + ...userOptions, + }; + let workingTree: UnitTestTree; + + // Build workspace + if (type === 'single') { + workingTree = await runner.runExternalSchematic( + '@schematics/angular', + 'ng-new', + SINGLE_APPLICATION_OPTIONS + ); + } else { + // Build workspace + workingTree = await runner.runExternalSchematic( + '@schematics/angular', + 'workspace', + WORKSPACE_OPTIONS + ); + // Build dummy application + workingTree = await runner.runExternalSchematic( + '@schematics/angular', + 'application', + MULTI_APPLICATION_OPTIONS, + workingTree + ); + // Build dummy library + workingTree = await runner.runExternalSchematic( + '@schematics/angular', + 'library', + MULTI_LIBRARY_OPTIONS, + workingTree + ); + } + + if (command !== 'ng-add') { + // We want to create update the proper files with `ng-add` + // First else the angular.json will have wrong data + workingTree = await runner.runSchematic('ng-add', options, workingTree); + } + + return await runner.runSchematic(command, options, workingTree); +} + +export async function runSchematic( + tree: UnitTestTree, + command: 'ng-add' | 'test', + options?: Record<string, any> +): Promise<UnitTestTree> { + const runner = new SchematicTestRunner( + 'schematics', + join(__dirname, '../../lib/schematics/collection.json') + ); + return await runner.runSchematic(command, options, tree); +} |