diff options
Diffstat (limited to 'remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add')
9 files changed, 288 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/.gitignore.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/.gitignore.template new file mode 100644 index 0000000000..f038b2eb67 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/.gitignore.template @@ -0,0 +1,2 @@ +# Compiled e2e tests output +build/ diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/app.__ext@dasherize__.ts.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/app.__ext@dasherize__.ts.template new file mode 100644 index 0000000000..60637d0fa7 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/app.__ext@dasherize__.ts.template @@ -0,0 +1,20 @@ +<% if(testRunner == 'node') { %> +import * as assert from 'assert'; +import {describe, it} from 'node:test'; +<% } %><% if(testRunner == 'mocha') { %> +import * as assert from 'assert'; +<% } %> +import {setupBrowserHooks, getBrowserState} from './utils'; + +describe('App test', function () { + setupBrowserHooks(); + it('is running', async function () { + const {page} = getBrowserState(); + const element = await page.locator('::-p-text(<%= project %>)').wait(); +<% if(testRunner == 'jasmine' || testRunner == 'jest') { %> + expect(element).not.toBeNull(); +<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %> + assert.ok(element); +<% } %> + }); +}); diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/utils.ts.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/utils.ts.template new file mode 100644 index 0000000000..2136f99a3a --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tests/utils.ts.template @@ -0,0 +1,60 @@ +<% if(testRunner == 'node') { %> +import {before, beforeEach, after, afterEach} from 'node:test'; +<% } %> +import * as puppeteer from 'puppeteer'; + +const baseUrl = process.env['baseUrl'] ?? '<%= baseUrl %>'; +let browser: puppeteer.Browser; +let page: puppeteer.Page; + +export function setupBrowserHooks(path = ''): void { +<% if(testRunner == 'jasmine' || testRunner == 'jest') { %> + beforeAll(async () => { + browser = await puppeteer.launch({ + headless: 'new' + }); + }); +<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %> + before(async () => { + browser = await puppeteer.launch({ + headless: 'new' + }); + }); +<% } %> + + beforeEach(async () => { + page = await browser.newPage(); + await page.goto(`${baseUrl}${path}`); + }); + + afterEach(async () => { + await page?.close(); + }); + +<% if(testRunner == 'jasmine' || testRunner == 'jest') { %> + afterAll(async () => { + await browser?.close(); + }); +<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %> + after(async () => { + await browser?.close(); + }); +<% } %> +} + +export function getBrowserState(): { + browser: puppeteer.Browser; + page: puppeteer.Page; + baseUrl: string; +} { + if (!browser) { + throw new Error( + 'No browser state found! Ensure `setupBrowserHooks()` is called.' + ); + } + return { + browser, + page, + baseUrl, + }; +} diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tsconfig.json.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tsconfig.json.template new file mode 100644 index 0000000000..38501b89ef --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/common/e2e/tsconfig.json.template @@ -0,0 +1,10 @@ +{ + "extends": "<%= tsConfigPath %>", + "compilerOptions": { + "module": "CommonJS", + "rootDir": "tests/", + "outDir": "build/", + "types": ["<%= testRunner %>"] + }, + "include": ["tests/**/*.ts"] +} diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/jasmine.json b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/jasmine.json new file mode 100644 index 0000000000..ad5dc6fbce --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/jasmine.json @@ -0,0 +1,10 @@ +{ + "spec_dir": "e2e", + "spec_files": ["**/*[eE]2[eE].js"], + "helpers": ["helpers/**/*.?(m)js"], + "env": { + "failSpecWithNoExpectations": true, + "stopSpecOnExpectationFailure": false, + "random": true + } +} diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jest/e2e/jest.config.js b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jest/e2e/jest.config.js new file mode 100644 index 0000000000..ee21c6737e --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jest/e2e/jest.config.js @@ -0,0 +1,10 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +/** @type {import('jest').Config} */ +module.exports = { + testMatch: ['<rootDir>/build/**/*.e2e.js'], + testEnvironment: 'node', +}; diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/.mocharc.js b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/.mocharc.js new file mode 100644 index 0000000000..28c1839674 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/.mocharc.js @@ -0,0 +1,4 @@ +module.exports = { + spec: './e2e/build/**/*.e2e.js', + timeout: 5000, +}; diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/index.ts b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/index.ts new file mode 100644 index 0000000000..1f962e0cfc --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/index.ts @@ -0,0 +1,135 @@ +/** + * @license + * Copyright 2022 Google Inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + chain, + type Rule, + type SchematicContext, + type Tree, +} from '@angular-devkit/schematics'; +import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks'; +import {of} from 'rxjs'; +import {concatMap, map, scan} from 'rxjs/operators'; + +import { + addCommonFiles as addCommonFilesHelper, + addFrameworkFiles, + getNgCommandName, + hasE2ETester, +} from '../utils/files.js'; +import {getApplicationProjects} from '../utils/json.js'; +import { + addPackageJsonDependencies, + addPackageJsonScripts, + getDependenciesFromOptions, + getPackageLatestNpmVersion, + DependencyType, + type NodePackage, + updateAngularJsonScripts, +} from '../utils/packages.js'; +import {TestRunner, type SchematicsOptions} from '../utils/types.js'; + +const DEFAULT_PORT = 4200; + +// You don't have to export the function as default. You can also have more than one rule +// factory per file. +export function ngAdd(options: SchematicsOptions): Rule { + return (tree: Tree, context: SchematicContext) => { + return chain([ + addDependencies(options), + addCommonFiles(options), + addOtherFiles(options), + updateScripts(), + updateAngularConfig(options), + ])(tree, context); + }; +} + +function addDependencies(options: SchematicsOptions): Rule { + return (tree: Tree, context: SchematicContext) => { + context.logger.debug('Adding dependencies to "package.json"'); + const dependencies = getDependenciesFromOptions(options); + + return of(...dependencies).pipe( + concatMap((packageName: string) => { + return getPackageLatestNpmVersion(packageName); + }), + scan((array, nodePackage) => { + array.push(nodePackage); + return array; + }, [] as NodePackage[]), + map(packages => { + context.logger.debug('Updating dependencies...'); + addPackageJsonDependencies(tree, packages, DependencyType.Dev); + context.addTask( + new NodePackageInstallTask({ + // Trigger Post-Install hooks to download the browser + allowScripts: true, + }) + ); + + return tree; + }) + ); + }; +} + +function updateScripts(): Rule { + return (tree: Tree, context: SchematicContext): Tree => { + context.logger.debug('Updating "package.json" scripts'); + const projects = getApplicationProjects(tree); + const projectsKeys = Object.keys(projects); + + if (projectsKeys.length === 1) { + const name = getNgCommandName(projects); + const prefix = hasE2ETester(projects) ? `run ${projectsKeys[0]}:` : ''; + return addPackageJsonScripts(tree, [ + { + name, + script: `ng ${prefix}${name}`, + }, + ]); + } + return tree; + }; +} + +function addCommonFiles(options: SchematicsOptions): Rule { + return (tree: Tree, context: SchematicContext) => { + context.logger.debug('Adding Puppeteer base files.'); + const projects = getApplicationProjects(tree); + + return addCommonFilesHelper(projects, { + options: { + ...options, + port: DEFAULT_PORT, + ext: options.testRunner === TestRunner.Node ? 'test' : 'e2e', + }, + }); + }; +} + +function addOtherFiles(options: SchematicsOptions): Rule { + return (tree: Tree, context: SchematicContext) => { + context.logger.debug('Adding Puppeteer additional files.'); + const projects = getApplicationProjects(tree); + + return addFrameworkFiles(projects, { + options: { + ...options, + port: DEFAULT_PORT, + }, + }); + }; +} + +function updateAngularConfig(options: SchematicsOptions): Rule { + return (tree: Tree, context: SchematicContext): Tree => { + context.logger.debug('Updating "angular.json".'); + + return updateAngularJsonScripts(tree, options); + }; +} diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/schema.json b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/schema.json new file mode 100644 index 0000000000..0fa581f1a7 --- /dev/null +++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "Puppeteer", + "title": "Puppeteer Install Schema", + "type": "object", + "properties": { + "testRunner": { + "type": "string", + "enum": ["jasmine", "jest", "mocha", "node"], + "default": "jasmine", + "alias": "t", + "x-prompt": { + "message": "Which test runners do you wish to use?", + "type": "list", + "items": [ + { + "value": "jasmine", + "label": "Use Jasmine [https://jasmine.github.io/]" + }, + { + "value": "jest", + "label": "Use Jest [https://jestjs.io/]" + }, + { + "value": "mocha", + "label": "Use Mocha [https://mochajs.org/]" + }, + { + "value": "node", + "label": "Use Node Test Runner [https://nodejs.org/api/test.html]" + } + ] + } + } + }, + "required": [] +} |