summaryrefslogtreecommitdiffstats
path: root/remote/test/puppeteer/packages/ng-schematics/src/schematics
diff options
context:
space:
mode:
Diffstat (limited to 'remote/test/puppeteer/packages/ng-schematics/src/schematics')
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/collection.json10
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/.puppeteerrc.cjs.template4
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.e2e.ts.template59
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template15
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/helpers/babel.js4
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/support/jasmine.json9
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jest/e2e/jest.config.js11
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/.mocharc.js4
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/babel.js4
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/node/e2e/.gitignore.template3
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/index.ts127
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/schema.json49
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/files.ts162
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/json.ts38
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/packages.ts204
-rw-r--r--remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/types.ts28
16 files changed, 731 insertions, 0 deletions
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/collection.json b/remote/test/puppeteer/packages/ng-schematics/src/schematics/collection.json
new file mode 100644
index 0000000000..0cf38b799b
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/collection.json
@@ -0,0 +1,10 @@
+{
+ "$schema": "../../../../node_modules/@angular-devkit/schematics/collection-schema.json",
+ "schematics": {
+ "ng-add": {
+ "description": "Add Puppeteer to an Angular project",
+ "factory": "./ng-add/index#ngAdd",
+ "schema": "./ng-add/schema.json"
+ }
+ }
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/.puppeteerrc.cjs.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/.puppeteerrc.cjs.template
new file mode 100644
index 0000000000..04f3f0d832
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/.puppeteerrc.cjs.template
@@ -0,0 +1,4 @@
+/**
+ * @type {import("puppeteer").Configuration}
+ */
+module.exports = {};
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.e2e.ts.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.e2e.ts.template
new file mode 100644
index 0000000000..2f98ef7d46
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tests/app.e2e.ts.template
@@ -0,0 +1,59 @@
+import * as puppeteer from 'puppeteer';
+<% if(testingFramework == 'node') { %>
+import {
+ describe,
+ it,
+ before,
+ beforeEach,
+ after,
+ afterEach,
+} from 'node:test';
+<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
+import * as assert from 'assert';
+<% } %>
+
+describe('App test', function () {
+ let browser: puppeteer.Browser;
+ let page: puppeteer.Page;
+
+<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
+ beforeAll(async () => {
+ browser = await puppeteer.launch();
+ });
+<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
+ before(async () => {
+ browser = await puppeteer.launch();
+ });
+<% } %>
+
+ beforeEach(async () => {
+ page = await browser.newPage();
+ await page.goto('<%= baseUrl %>');
+ });
+
+ afterEach(async () => {
+ await page.close();
+ });
+
+<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
+ afterAll(async () => {
+ await browser.close();
+ });
+<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
+ after(async () => {
+ await browser.close();
+ });
+<% } %>
+
+ it('is running', async function () {
+ const element = await page.waitForSelector(
+ 'text/<%= project %> app is running!'
+ );
+
+<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
+ expect(element).not.toBeNull();
+<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
+ assert.ok(element);
+<% } %>
+ });
+});
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template
new file mode 100644
index 0000000000..438d04725f
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/base/e2e/tsconfig.json.template
@@ -0,0 +1,15 @@
+/* To learn more about this file see: https://angular.io/config/tsconfig. */
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+<% if(testingFramework == 'jest') { %>
+ "esModuleInterop": true,
+<% } %><% if(testingFramework == 'node') { %>
+ "module": "CommonJS",
+ "rootDir": "tests/",
+ "outDir": "test/",
+<% } %>
+ "types": ["<%= testingFramework %>"]
+ },
+ "include": ["tests/**/*.e2e.ts"]
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/helpers/babel.js b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/helpers/babel.js
new file mode 100644
index 0000000000..06259b39c8
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/helpers/babel.js
@@ -0,0 +1,4 @@
+require('@babel/register')({
+ extensions: ['.js', '.ts'],
+ presets: ['@babel/preset-env', '@babel/preset-typescript'],
+});
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/support/jasmine.json b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/support/jasmine.json
new file mode 100644
index 0000000000..7100e102f1
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jasmine/e2e/support/jasmine.json
@@ -0,0 +1,9 @@
+{
+ "spec_dir": "e2e",
+ "spec_files": ["**/*[eE]2[eE].ts"],
+ "helpers": ["helpers/babel.js", "helpers/**/*.{js|ts}"],
+ "env": {
+ "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..99cc594c97
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/jest/e2e/jest.config.js
@@ -0,0 +1,11 @@
+/*
+ * For a detailed explanation regarding each configuration property and type check, visit:
+ * https://jestjs.io/docs/configuration
+ */
+
+/** @type {import('ts-jest').JestConfigWithTsJest} */
+module.exports = {
+ testMatch: ['<rootDir>/tests/**/?(*.)+(e2e).[tj]s?(x)'],
+ preset: 'ts-jest',
+ 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..63ca85e3eb
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/.mocharc.js
@@ -0,0 +1,4 @@
+module.exports = {
+ file: ['e2e/babel.js'],
+ spec: './e2e/tests/**/*.e2e.ts',
+};
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/babel.js b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/babel.js
new file mode 100644
index 0000000000..06259b39c8
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/mocha/e2e/babel.js
@@ -0,0 +1,4 @@
+require('@babel/register')({
+ extensions: ['.js', '.ts'],
+ presets: ['@babel/preset-env', '@babel/preset-typescript'],
+});
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/node/e2e/.gitignore.template b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/node/e2e/.gitignore.template
new file mode 100644
index 0000000000..35250fac0e
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/files/node/e2e/.gitignore.template
@@ -0,0 +1,3 @@
+# Compiled e2e tests output Node auto resolves files in folders named 'test'
+
+test/ \ No newline at end of file
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..49c56bfc2f
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/index.ts
@@ -0,0 +1,127 @@
+/**
+ * Copyright 2022 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {chain, Rule, SchematicContext, Tree} from '@angular-devkit/schematics';
+import {NodePackageInstallTask} from '@angular-devkit/schematics/tasks';
+import {of} from 'rxjs';
+import {concatMap, map, scan} from 'rxjs/operators';
+
+import {
+ addBaseFiles,
+ addFrameworkFiles,
+ getNgCommandName,
+} from '../utils/files.js';
+import {getAngularConfig} from '../utils/json.js';
+import {
+ addPackageJsonDependencies,
+ addPackageJsonScripts,
+ getDependenciesFromOptions,
+ getPackageLatestNpmVersion,
+ DependencyType,
+ type NodePackage,
+ updateAngularJsonScripts,
+} from '../utils/packages.js';
+import {type SchematicsOptions} from '../utils/types.js';
+
+// 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),
+ addPuppeteerFiles(options),
+ addOtherFiles(options),
+ updateScripts(options),
+ 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());
+
+ return tree;
+ })
+ );
+ };
+}
+
+function updateScripts(options: SchematicsOptions): Rule {
+ return (tree: Tree, context: SchematicContext): Tree => {
+ context.logger.debug('Updating "package.json" scripts');
+ const angularJson = getAngularConfig(tree);
+ const projects = Object.keys(angularJson['projects']);
+
+ if (projects.length === 1) {
+ const name = getNgCommandName(options);
+ const prefix = options.isDefaultTester ? '' : `run ${projects[0]}:`;
+ return addPackageJsonScripts(tree, [
+ {
+ name,
+ script: `ng ${prefix}${name}`,
+ },
+ ]);
+ }
+ return tree;
+ };
+}
+
+function addPuppeteerFiles(options: SchematicsOptions): Rule {
+ return (tree: Tree, context: SchematicContext) => {
+ context.logger.debug('Adding Puppeteer base files.');
+ const {projects} = getAngularConfig(tree);
+
+ return addBaseFiles(tree, context, {
+ projects,
+ options,
+ });
+ };
+}
+
+function addOtherFiles(options: SchematicsOptions): Rule {
+ return (tree: Tree, context: SchematicContext) => {
+ context.logger.debug('Adding Puppeteer additional files.');
+ const {projects} = getAngularConfig(tree);
+
+ return addFrameworkFiles(tree, context, {
+ projects,
+ options,
+ });
+ };
+}
+
+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..77cb5bdd48
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/ng-add/schema.json
@@ -0,0 +1,49 @@
+{
+ "$schema": "http://json-schema.org/schema",
+ "$id": "Puppeteer",
+ "title": "Puppeteer Install Schema",
+ "type": "object",
+ "properties": {
+ "isDefaultTester": {
+ "description": "",
+ "type": "boolean",
+ "default": true,
+ "x-prompt": "Use Puppeteer as default `ng e2e` command?"
+ },
+ "exportConfig": {
+ "description": "",
+ "type": "boolean",
+ "default": false,
+ "x-prompt": "Export default Puppeteer config file?"
+ },
+ "testingFramework": {
+ "description": "",
+ "type": "string",
+ "enum": ["jasmine", "jest", "mocha", "node"],
+ "default": "jasmine",
+ "x-prompt": {
+ "message": "With what Testing Library do you wish to integrate?",
+ "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 (Experimental: Node v18) [https://nodejs.org/api/test.html]"
+ }
+ ]
+ }
+ }
+ },
+ "required": []
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/files.ts b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/files.ts
new file mode 100644
index 0000000000..9518e1d996
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/files.ts
@@ -0,0 +1,162 @@
+/**
+ * Copyright 2022 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {relative, resolve} from 'path';
+
+import {getSystemPath, normalize, strings} from '@angular-devkit/core';
+import {
+ SchematicContext,
+ Tree,
+ apply,
+ applyTemplates,
+ chain,
+ filter,
+ mergeWith,
+ move,
+ url,
+} from '@angular-devkit/schematics';
+
+import {SchematicsOptions, TestingFramework} from './types.js';
+
+export interface FilesOptions {
+ projects: any;
+ options: SchematicsOptions;
+ applyPath: string;
+ relativeToWorkspacePath: string;
+ movePath?: string;
+ filterPredicate?: (path: string) => boolean;
+}
+
+const PUPPETEER_CONFIG_TEMPLATE = '.puppeteerrc.cjs.template';
+
+export function addFiles(
+ tree: Tree,
+ context: SchematicContext,
+ {
+ projects,
+ options,
+ applyPath,
+ movePath,
+ relativeToWorkspacePath,
+ filterPredicate,
+ }: FilesOptions
+): any {
+ return chain(
+ Object.keys(projects).map(name => {
+ const project = projects[name];
+ const projectPath = resolve(getSystemPath(normalize(project.root)));
+ const workspacePath = resolve(getSystemPath(normalize('')));
+
+ const relativeToWorkspace = relative(
+ `${projectPath}${relativeToWorkspacePath}`,
+ workspacePath
+ );
+
+ const baseUrl = getProjectBaseUrl(project);
+
+ return mergeWith(
+ apply(url(applyPath), [
+ filter(
+ filterPredicate ??
+ (() => {
+ return true;
+ })
+ ),
+ move(movePath ? `${project.root}${movePath}` : project.root),
+ applyTemplates({
+ ...options,
+ ...strings,
+ root: project.root ? `${project.root}/` : project.root,
+ baseUrl,
+ project: name,
+ relativeToWorkspace,
+ }),
+ ])
+ );
+ })
+ )(tree, context);
+}
+
+function getProjectBaseUrl(project: any): string {
+ let options = {protocol: 'http', port: 4200, host: 'localhost'};
+
+ if (project.architect?.serve?.options) {
+ const projectOptions = project.architect?.serve?.options;
+
+ options = {...options, ...projectOptions};
+ options.protocol = projectOptions.ssl ? 'https' : 'http';
+ }
+
+ return `${options.protocol}://${options.host}:${options.port}`;
+}
+
+export function addBaseFiles(
+ tree: Tree,
+ context: SchematicContext,
+ filesOptions: Omit<FilesOptions, 'applyPath' | 'relativeToWorkspacePath'>
+): any {
+ const options: FilesOptions = {
+ ...filesOptions,
+ applyPath: './files/base',
+ relativeToWorkspacePath: `/`,
+ filterPredicate: path => {
+ return path.includes(PUPPETEER_CONFIG_TEMPLATE) &&
+ !filesOptions.options.exportConfig
+ ? false
+ : true;
+ },
+ };
+
+ return addFiles(tree, context, options);
+}
+
+export function addFrameworkFiles(
+ tree: Tree,
+ context: SchematicContext,
+ filesOptions: Omit<FilesOptions, 'applyPath' | 'relativeToWorkspacePath'>
+): any {
+ const testingFramework = filesOptions.options.testingFramework;
+ const options: FilesOptions = {
+ ...filesOptions,
+ applyPath: `./files/${testingFramework}`,
+ relativeToWorkspacePath: `/`,
+ };
+
+ return addFiles(tree, context, options);
+}
+
+export function getScriptFromOptions(options: SchematicsOptions): string[][] {
+ switch (options.testingFramework) {
+ case TestingFramework.Jasmine:
+ return [[`jasmine`, '--config=./e2e/support/jasmine.json']];
+ case TestingFramework.Jest:
+ return [[`jest`, '-c', 'e2e/jest.config.js']];
+ case TestingFramework.Mocha:
+ return [[`mocha`, '--config=./e2e/.mocharc.js']];
+ case TestingFramework.Node:
+ return [
+ [`tsc`, '-p', 'e2e/tsconfig.json'],
+ ['node', '--test', 'e2e/'],
+ ];
+ }
+}
+
+export function getNgCommandName(options: SchematicsOptions): string {
+ if (options.isDefaultTester) {
+ return 'e2e';
+ }
+ return 'puppeteer';
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/json.ts b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/json.ts
new file mode 100644
index 0000000000..f48eab399e
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/json.ts
@@ -0,0 +1,38 @@
+/**
+ * Copyright 2022 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {SchematicsException, Tree} from '@angular-devkit/schematics';
+
+export function getJsonFileAsObject(
+ tree: Tree,
+ path: string
+): Record<string, any> {
+ try {
+ const buffer = tree.read(path) as Buffer;
+ const content = buffer.toString();
+ return JSON.parse(content);
+ } catch {
+ throw new SchematicsException(`Unable to retrieve file at ${path}.`);
+ }
+}
+
+export function getObjectAsJson(object: Record<string, any>): string {
+ return JSON.stringify(object, null, 2);
+}
+
+export function getAngularConfig(tree: Tree): Record<string, any> {
+ return getJsonFileAsObject(tree, './angular.json');
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/packages.ts b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/packages.ts
new file mode 100644
index 0000000000..b3724be90f
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/packages.ts
@@ -0,0 +1,204 @@
+/**
+ * Copyright 2022 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {get} from 'https';
+
+import {Tree} from '@angular-devkit/schematics';
+
+import {getNgCommandName, getScriptFromOptions} from './files.js';
+import {
+ getAngularConfig,
+ getJsonFileAsObject,
+ getObjectAsJson,
+} from './json.js';
+import {SchematicsOptions, TestingFramework} from './types.js';
+export interface NodePackage {
+ name: string;
+ version: string;
+}
+export interface NodeScripts {
+ name: string;
+ script: string;
+}
+
+export enum DependencyType {
+ Default = 'dependencies',
+ Dev = 'devDependencies',
+ Peer = 'peerDependencies',
+ Optional = 'optionalDependencies',
+}
+
+export function getPackageLatestNpmVersion(name: string): Promise<NodePackage> {
+ return new Promise(resolve => {
+ let version = 'latest';
+
+ return get(`https://registry.npmjs.org/${name}`, res => {
+ let data = '';
+
+ res.on('data', (chunk: any) => {
+ data += chunk;
+ });
+ res.on('end', () => {
+ try {
+ const response = JSON.parse(data);
+ version = response?.['dist-tags']?.latest ?? version;
+ } catch {
+ } finally {
+ resolve({
+ name,
+ version,
+ });
+ }
+ });
+ }).on('error', () => {
+ resolve({
+ name,
+ version,
+ });
+ });
+ });
+}
+
+function updateJsonValues(
+ json: Record<string, any>,
+ target: string,
+ updates: Array<{name: string; value: any}>,
+ overwrite = false
+) {
+ updates.forEach(({name, value}) => {
+ if (!json[target][name] || overwrite) {
+ json[target] = {
+ ...json[target],
+ [name]: value,
+ };
+ }
+ });
+}
+
+export function addPackageJsonDependencies(
+ tree: Tree,
+ packages: NodePackage[],
+ type: DependencyType,
+ overwrite?: boolean,
+ fileLocation = './package.json'
+): Tree {
+ const packageJson = getJsonFileAsObject(tree, fileLocation);
+
+ updateJsonValues(
+ packageJson,
+ type,
+ packages.map(({name, version}) => {
+ return {name, value: version};
+ }),
+ overwrite
+ );
+
+ tree.overwrite(fileLocation, getObjectAsJson(packageJson));
+
+ return tree;
+}
+
+export function getDependenciesFromOptions(
+ options: SchematicsOptions
+): string[] {
+ const dependencies = ['puppeteer'];
+ const babelPackages = [
+ '@babel/core',
+ '@babel/register',
+ '@babel/preset-env',
+ '@babel/preset-typescript',
+ ];
+
+ switch (options.testingFramework) {
+ case TestingFramework.Jasmine:
+ dependencies.push('jasmine', ...babelPackages);
+ break;
+ case TestingFramework.Jest:
+ dependencies.push('jest', '@types/jest', 'ts-jest');
+ break;
+ case TestingFramework.Mocha:
+ dependencies.push('mocha', '@types/mocha', ...babelPackages);
+ break;
+ case TestingFramework.Node:
+ dependencies.push('@types/node');
+ break;
+ }
+
+ return dependencies;
+}
+
+export function addPackageJsonScripts(
+ tree: Tree,
+ scripts: NodeScripts[],
+ overwrite?: boolean,
+ fileLocation = './package.json'
+): Tree {
+ const packageJson = getJsonFileAsObject(tree, fileLocation);
+
+ updateJsonValues(
+ packageJson,
+ 'scripts',
+ scripts.map(({name, script}) => {
+ return {name, value: script};
+ }),
+ overwrite
+ );
+
+ tree.overwrite(fileLocation, getObjectAsJson(packageJson));
+
+ return tree;
+}
+
+export function updateAngularJsonScripts(
+ tree: Tree,
+ options: SchematicsOptions,
+ overwrite = true
+): Tree {
+ const angularJson = getAngularConfig(tree);
+ const commands = getScriptFromOptions(options);
+ const name = getNgCommandName(options);
+
+ Object.keys(angularJson['projects']).forEach(project => {
+ const e2eScript = [
+ {
+ name,
+ value: {
+ builder: '@puppeteer/ng-schematics:puppeteer',
+ options: {
+ commands,
+ devServerTarget: `${project}:serve`,
+ },
+ configurations: {
+ production: {
+ devServerTarget: `${project}:serve:production`,
+ },
+ },
+ },
+ },
+ ];
+
+ updateJsonValues(
+ angularJson['projects'][project],
+ 'architect',
+ e2eScript,
+ overwrite
+ );
+ });
+
+ tree.overwrite('./angular.json', getObjectAsJson(angularJson));
+
+ return tree;
+}
diff --git a/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/types.ts b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/types.ts
new file mode 100644
index 0000000000..c59f90e69d
--- /dev/null
+++ b/remote/test/puppeteer/packages/ng-schematics/src/schematics/utils/types.ts
@@ -0,0 +1,28 @@
+/**
+ * Copyright 2022 Google Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export enum TestingFramework {
+ Jasmine = 'jasmine',
+ Jest = 'jest',
+ Mocha = 'mocha',
+ Node = 'node',
+}
+
+export interface SchematicsOptions {
+ isDefaultTester: boolean;
+ exportConfig: boolean;
+ testingFramework: TestingFramework;
+}