mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore(ng-schematics): refactor away user-side complexity (#10750)
This commit is contained in:
parent
de719dbb86
commit
35dc2d8840
@ -14,7 +14,7 @@ ng add @puppeteer/ng-schematics
|
|||||||
|
|
||||||
Or you can use the same command followed by the [options](#options) below.
|
Or you can use the same command followed by the [options](#options) below.
|
||||||
|
|
||||||
Currently, this schematic supports the following test frameworks:
|
Currently, this schematic supports the following test runners:
|
||||||
|
|
||||||
- [**Jasmine**](https://jasmine.github.io/)
|
- [**Jasmine**](https://jasmine.github.io/)
|
||||||
- [**Jest**](https://jestjs.io/)
|
- [**Jest**](https://jestjs.io/)
|
||||||
@ -32,11 +32,8 @@ ng e2e
|
|||||||
When adding schematics to your project you can to provide following options:
|
When adding schematics to your project you can to provide following options:
|
||||||
|
|
||||||
| Option | Description | Value | Required |
|
| Option | Description | Value | Required |
|
||||||
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -------- |
|
| -------------- | ------------------------------------------------------ | ------------------------------------------ | -------- |
|
||||||
| `--isDefaultTester` | When true, replaces default `ng e2e` command. | `boolean` | `true` |
|
| `--testRunner` | The testing framework to install along side Puppeteer. | `"jasmine"`, `"jest"`, `"mocha"`, `"node"` | `true` |
|
||||||
| `--exportConfig` | When true, creates an empty [Puppeteer configuration](https://pptr.dev/guides/configuration) file. (`.puppeteerrc.cjs`) | `boolean` | `true` |
|
|
||||||
| `--testingFramework` | The testing framework to install along side Puppeteer. | `"jasmine"`, `"jest"`, `"mocha"`, `"node"` | `true` |
|
|
||||||
| `--port` | The port to spawn server for E2E. If default is used `ng serve` and `ng e2e` will not run side-by-side. | `number` | `4200` |
|
|
||||||
|
|
||||||
## Creating a single test file
|
## Creating a single test file
|
||||||
|
|
||||||
@ -59,7 +56,7 @@ Update either `e2e` or `puppeteer` (depending on the initial setup) to:
|
|||||||
"options": {
|
"options": {
|
||||||
"commands": [...],
|
"commands": [...],
|
||||||
"devServerTarget": "sandbox:serve",
|
"devServerTarget": "sandbox:serve",
|
||||||
"testingFramework": "<TestingFramework>",
|
"testRunner": "<TestRunner>",
|
||||||
"port": 8080
|
"port": 8080
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
|
@ -14,7 +14,7 @@ ng add @puppeteer/ng-schematics
|
|||||||
|
|
||||||
Or you can use the same command followed by the [options](#options) below.
|
Or you can use the same command followed by the [options](#options) below.
|
||||||
|
|
||||||
Currently, this schematic supports the following test frameworks:
|
Currently, this schematic supports the following test runners:
|
||||||
|
|
||||||
- [**Jasmine**](https://jasmine.github.io/)
|
- [**Jasmine**](https://jasmine.github.io/)
|
||||||
- [**Jest**](https://jestjs.io/)
|
- [**Jest**](https://jestjs.io/)
|
||||||
@ -32,11 +32,8 @@ ng e2e
|
|||||||
When adding schematics to your project you can to provide following options:
|
When adding schematics to your project you can to provide following options:
|
||||||
|
|
||||||
| Option | Description | Value | Required |
|
| Option | Description | Value | Required |
|
||||||
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -------- |
|
| -------------- | ------------------------------------------------------ | ------------------------------------------ | -------- |
|
||||||
| `--isDefaultTester` | When true, replaces default `ng e2e` command. | `boolean` | `true` |
|
| `--testRunner` | The testing framework to install along side Puppeteer. | `"jasmine"`, `"jest"`, `"mocha"`, `"node"` | `true` |
|
||||||
| `--exportConfig` | When true, creates an empty [Puppeteer configuration](https://pptr.dev/guides/configuration) file. (`.puppeteerrc.cjs`) | `boolean` | `true` |
|
|
||||||
| `--testingFramework` | The testing framework to install along side Puppeteer. | `"jasmine"`, `"jest"`, `"mocha"`, `"node"` | `true` |
|
|
||||||
| `--port` | The port to spawn server for E2E. If default is used `ng serve` and `ng e2e` will not run side-by-side. | `number` | `4200` |
|
|
||||||
|
|
||||||
## Creating a single test file
|
## Creating a single test file
|
||||||
|
|
||||||
@ -59,7 +56,7 @@ Update either `e2e` or `puppeteer` (depending on the initial setup) to:
|
|||||||
"options": {
|
"options": {
|
||||||
"commands": [...],
|
"commands": [...],
|
||||||
"devServerTarget": "sandbox:serve",
|
"devServerTarget": "sandbox:serve",
|
||||||
"testingFramework": "<TestingFramework>",
|
"testRunner": "<TestRunner>",
|
||||||
"port": 8080
|
"port": 8080
|
||||||
},
|
},
|
||||||
...
|
...
|
||||||
|
@ -9,6 +9,8 @@ import {
|
|||||||
} from '@angular-devkit/architect';
|
} from '@angular-devkit/architect';
|
||||||
import {JsonObject} from '@angular-devkit/core';
|
import {JsonObject} from '@angular-devkit/core';
|
||||||
|
|
||||||
|
import {TestRunner} from '../../schematics/utils/types.js';
|
||||||
|
|
||||||
import {PuppeteerBuilderOptions} from './types.js';
|
import {PuppeteerBuilderOptions} from './types.js';
|
||||||
|
|
||||||
const terminalStyles = {
|
const terminalStyles = {
|
||||||
@ -39,13 +41,35 @@ function getExecutable(command: string[]) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateExecutablePath(command: string, root?: string) {
|
||||||
|
let path = 'node_modules/.bin/';
|
||||||
|
if (root && root !== '' && command === TestRunner.Node) {
|
||||||
|
const nested = root
|
||||||
|
.split('/')
|
||||||
|
.map(() => {
|
||||||
|
return '../';
|
||||||
|
})
|
||||||
|
.join('');
|
||||||
|
path = `${nested}${path}${command}`;
|
||||||
|
} else {
|
||||||
|
path = `./${path}${command}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
async function executeCommand(context: BuilderContext, command: string[]) {
|
async function executeCommand(context: BuilderContext, command: string[]) {
|
||||||
|
let project: JsonObject;
|
||||||
|
if (context.target) {
|
||||||
|
project = await context.getProjectMetadata(context.target.project);
|
||||||
|
command[0] = updateExecutablePath(command[0]!, String(project['root']));
|
||||||
|
}
|
||||||
|
|
||||||
await new Promise(async (resolve, reject) => {
|
await new Promise(async (resolve, reject) => {
|
||||||
context.logger.debug(`Trying to execute command - ${command.join(' ')}.`);
|
context.logger.debug(`Trying to execute command - ${command.join(' ')}.`);
|
||||||
const {executable, args, error} = getExecutable(command);
|
const {executable, args, error} = getExecutable(command);
|
||||||
let path = context.workspaceRoot;
|
let path = context.workspaceRoot;
|
||||||
if (context.target) {
|
if (context.target) {
|
||||||
const project = await context.getProjectMetadata(context.target.project);
|
|
||||||
path = `${path}/${project['root']}`;
|
path = `${path}/${project['root']}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +147,13 @@ async function executeE2ETest(
|
|||||||
try {
|
try {
|
||||||
server = await startServer(options, context);
|
server = await startServer(options, context);
|
||||||
|
|
||||||
|
const commands = options.commands;
|
||||||
|
|
||||||
|
message('\n Building tests 🛠️ ... \n', context);
|
||||||
|
await executeCommand(context, [`tsc`, '-p', 'e2e/tsconfig.json']);
|
||||||
|
|
||||||
message('\n Running tests 🧪 ... \n', context);
|
message('\n Running tests 🧪 ... \n', context);
|
||||||
for (const command of options.commands) {
|
for (const command of commands) {
|
||||||
await executeCommand(context, command);
|
await executeCommand(context, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,10 +6,15 @@
|
|||||||
"factory": "./ng-add/index#ngAdd",
|
"factory": "./ng-add/index#ngAdd",
|
||||||
"schema": "./ng-add/schema.json"
|
"schema": "./ng-add/schema.json"
|
||||||
},
|
},
|
||||||
"test": {
|
"e2e": {
|
||||||
"description": "Create a single test file",
|
"description": "Create a single test file",
|
||||||
"factory": "./test/index#test",
|
"factory": "./e2e/index#e2e",
|
||||||
"schema": "./test/schema.json"
|
"schema": "./e2e/schema.json"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"description": "Eject Puppeteer config file",
|
||||||
|
"factory": "./config/index#config",
|
||||||
|
"schema": "./config/schema.json"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* @type {import("puppeteer").Configuration}
|
* @type {import("puppeteer").Configuration}
|
||||||
*/
|
*/
|
||||||
module.exports = {};
|
export {};
|
44
packages/ng-schematics/src/schematics/config/index.ts
Normal file
44
packages/ng-schematics/src/schematics/config/index.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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 {addFilesSingle} from '../utils/files.js';
|
||||||
|
import {TestRunner, AngularProject} 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 config(): Rule {
|
||||||
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
|
return chain([addPuppeteerConfig()])(tree, context);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addPuppeteerConfig(): Rule {
|
||||||
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
|
context.logger.debug('Adding Puppeteer config file.');
|
||||||
|
|
||||||
|
return addFilesSingle(tree, context, '', {root: ''} as AngularProject, {
|
||||||
|
// No-op here to fill types
|
||||||
|
options: {
|
||||||
|
testRunner: TestRunner.Jasmine,
|
||||||
|
port: 4200,
|
||||||
|
},
|
||||||
|
applyPath: './files',
|
||||||
|
relativeToWorkspacePath: `/`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
8
packages/ng-schematics/src/schematics/config/schema.json
Normal file
8
packages/ng-schematics/src/schematics/config/schema.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"$id": "Puppeteer",
|
||||||
|
"title": "Puppeteer Config Schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {},
|
||||||
|
"required": []
|
||||||
|
}
|
@ -1,13 +1,17 @@
|
|||||||
<% if(testingFramework == 'node') { %>
|
<% if(testRunner == 'node') { %>
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import {describe, it} from 'node:test';
|
import {describe, it} from 'node:test';
|
||||||
<% } %><% if(testingFramework == 'mocha') { %>
|
<% } %><% if(testRunner == 'mocha') { %>
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
<% } %>
|
<% } %>
|
||||||
import {setupBrowserHooks, getBrowserState} from './utils';
|
import {setupBrowserHooks, getBrowserState} from './utils';
|
||||||
|
|
||||||
describe('<%= classify(name) %>', function () {
|
describe('<%= classify(name) %>', function () {
|
||||||
|
<% if(route) { %>
|
||||||
|
setupBrowserHooks('<%= route %>');
|
||||||
|
<% } else { %>
|
||||||
setupBrowserHooks();
|
setupBrowserHooks();
|
||||||
|
<% } %>
|
||||||
it('', async function () {
|
it('', async function () {
|
||||||
const {page} = getBrowserState();
|
const {page} = getBrowserState();
|
||||||
});
|
});
|
@ -25,19 +25,19 @@ import {
|
|||||||
import {addCommonFiles} from '../utils/files.js';
|
import {addCommonFiles} from '../utils/files.js';
|
||||||
import {getAngularConfig} from '../utils/json.js';
|
import {getAngularConfig} from '../utils/json.js';
|
||||||
import {
|
import {
|
||||||
TestingFramework,
|
TestRunner,
|
||||||
SchematicsSpec,
|
SchematicsSpec,
|
||||||
SchematicsOptions,
|
|
||||||
AngularProject,
|
AngularProject,
|
||||||
|
PuppeteerSchematicsConfig,
|
||||||
} from '../utils/types.js';
|
} from '../utils/types.js';
|
||||||
|
|
||||||
// You don't have to export the function as default. You can also have more than one rule
|
// You don't have to export the function as default. You can also have more than one rule
|
||||||
// factory per file.
|
// factory per file.
|
||||||
export function test(userArgs: Record<string, string>): Rule {
|
export function e2e(userArgs: Record<string, string>): Rule {
|
||||||
const options = parseUserTestArgs(userArgs);
|
const options = parseUserTestArgs(userArgs);
|
||||||
|
|
||||||
return (tree: Tree, context: SchematicContext) => {
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
return chain([addSpecFile(options)])(tree, context);
|
return chain([addE2EFile(options)])(tree, context);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,14 +51,19 @@ function parseUserTestArgs(userArgs: Record<string, string>): SchematicsSpec {
|
|||||||
if ('n' in userArgs) {
|
if ('n' in userArgs) {
|
||||||
options['name'] = userArgs['n'];
|
options['name'] = userArgs['n'];
|
||||||
}
|
}
|
||||||
|
if ('r' in userArgs) {
|
||||||
|
options['route'] = userArgs['n'];
|
||||||
|
}
|
||||||
|
|
||||||
return options as SchematicsSpec;
|
return options as SchematicsSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findTestingOption<Property extends keyof SchematicsOptions>(
|
function findTestingOption<
|
||||||
|
Property extends keyof PuppeteerSchematicsConfig['options'],
|
||||||
|
>(
|
||||||
[name, project]: [string, AngularProject | undefined],
|
[name, project]: [string, AngularProject | undefined],
|
||||||
property: Property
|
property: Property
|
||||||
): SchematicsOptions[Property] {
|
): PuppeteerSchematicsConfig['options'][Property] {
|
||||||
if (!project) {
|
if (!project) {
|
||||||
throw new Error(`Project "${name}" not found.`);
|
throw new Error(`Project "${name}" not found.`);
|
||||||
}
|
}
|
||||||
@ -76,7 +81,7 @@ function findTestingOption<Property extends keyof SchematicsOptions>(
|
|||||||
throw new Error(`Can't find property "${property}" for project "${name}".`);
|
throw new Error(`Can't find property "${property}" for project "${name}".`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSpecFile(options: SchematicsSpec): Rule {
|
function addE2EFile(options: SchematicsSpec): Rule {
|
||||||
return async (tree: Tree, context: SchematicContext) => {
|
return async (tree: Tree, context: SchematicContext) => {
|
||||||
context.logger.debug('Adding Spec file.');
|
context.logger.debug('Adding Spec file.');
|
||||||
|
|
||||||
@ -96,10 +101,7 @@ function addSpecFile(options: SchematicsSpec): Rule {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const testingFramework = findTestingOption(
|
const testRunner = findTestingOption(foundProject, 'testRunner');
|
||||||
foundProject,
|
|
||||||
'testingFramework'
|
|
||||||
);
|
|
||||||
const port = findTestingOption(foundProject, 'port');
|
const port = findTestingOption(foundProject, 'port');
|
||||||
|
|
||||||
context.logger.debug('Creating Spec file.');
|
context.logger.debug('Creating Spec file.');
|
||||||
@ -111,10 +113,11 @@ function addSpecFile(options: SchematicsSpec): Rule {
|
|||||||
{
|
{
|
||||||
options: {
|
options: {
|
||||||
name: options.name,
|
name: options.name,
|
||||||
testingFramework,
|
route: options.route,
|
||||||
|
testRunner,
|
||||||
// Node test runner does not support glob patterns
|
// Node test runner does not support glob patterns
|
||||||
// It looks for files `*.test.js`
|
// It looks for files `*.test.js`
|
||||||
ext: testingFramework === TestingFramework.Node ? 'test' : 'e2e',
|
ext: testRunner === TestRunner.Node ? 'test' : 'e2e',
|
||||||
port,
|
port,
|
||||||
},
|
},
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/schema",
|
"$schema": "http://json-schema.org/schema",
|
||||||
"$id": "Puppeteer",
|
"$id": "Puppeteer",
|
||||||
"title": "Puppeteer Spec Schema",
|
"title": "Puppeteer E2E Schema",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"name": {
|
"name": {
|
||||||
@ -20,6 +20,14 @@
|
|||||||
"index": 1
|
"index": 1
|
||||||
},
|
},
|
||||||
"alias": "p"
|
"alias": "p"
|
||||||
|
},
|
||||||
|
"route": {
|
||||||
|
"type": "string",
|
||||||
|
"$default": {
|
||||||
|
"$source": "argv",
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"alias": "r"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
@ -1,7 +1,7 @@
|
|||||||
<% if(testingFramework == 'node') { %>
|
<% if(testRunner == 'node') { %>
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import {describe, it} from 'node:test';
|
import {describe, it} from 'node:test';
|
||||||
<% } %><% if(testingFramework == 'mocha') { %>
|
<% } %><% if(testRunner == 'mocha') { %>
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
<% } %>
|
<% } %>
|
||||||
import {setupBrowserHooks, getBrowserState} from './utils';
|
import {setupBrowserHooks, getBrowserState} from './utils';
|
||||||
@ -12,9 +12,9 @@ describe('App test', function () {
|
|||||||
const {page} = getBrowserState();
|
const {page} = getBrowserState();
|
||||||
const element = await page.waitForSelector('text/<%= project %> app is running!');
|
const element = await page.waitForSelector('text/<%= project %> app is running!');
|
||||||
|
|
||||||
<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
|
<% if(testRunner == 'jasmine' || testRunner == 'jest') { %>
|
||||||
expect(element).not.toBeNull();
|
expect(element).not.toBeNull();
|
||||||
<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
|
<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %>
|
||||||
assert.ok(element);
|
assert.ok(element);
|
||||||
<% } %>
|
<% } %>
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<% if(testingFramework == 'node') { %>
|
<% if(testRunner == 'node') { %>
|
||||||
import {before, beforeEach, after, afterEach} from 'node:test';
|
import {before, beforeEach, after, afterEach} from 'node:test';
|
||||||
<% } %>
|
<% } %>
|
||||||
import * as puppeteer from 'puppeteer';
|
import * as puppeteer from 'puppeteer';
|
||||||
@ -7,33 +7,35 @@ const baseUrl = '<%= baseUrl %>';
|
|||||||
let browser: puppeteer.Browser;
|
let browser: puppeteer.Browser;
|
||||||
let page: puppeteer.Page;
|
let page: puppeteer.Page;
|
||||||
|
|
||||||
export function setupBrowserHooks(): void {
|
export function setupBrowserHooks(path = '/'): void {
|
||||||
<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
|
<% if(testRunner == 'jasmine' || testRunner == 'jest') { %>
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
browser = await puppeteer.launch({
|
browser = await puppeteer.launch({
|
||||||
headless: 'new'
|
headless: 'new'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
|
<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %>
|
||||||
before(async () => {
|
before(async () => {
|
||||||
browser = await puppeteer.launch();
|
browser = await puppeteer.launch({
|
||||||
|
headless: 'new'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
page = await browser.newPage();
|
page = await browser.newPage();
|
||||||
await page.goto(baseUrl);
|
await page.goto(`${baseUrl}${path}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await page.close();
|
await page.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
<% if(testingFramework == 'jasmine' || testingFramework == 'jest') { %>
|
<% if(testRunner == 'jasmine' || testRunner == 'jest') { %>
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
<% } %><% if(testingFramework == 'mocha' || testingFramework == 'node') { %>
|
<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %>
|
||||||
after(async () => {
|
after(async () => {
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"extends": "<%= tsConfigPath %>",
|
"extends": "<%= tsConfigPath %>",
|
||||||
"compilerOptions": {<% if(testingFramework == 'jest') { %>
|
"compilerOptions": {
|
||||||
"esModuleInterop": true,<% } %><% if(testingFramework == 'node') { %>
|
|
||||||
"module": "CommonJS",
|
"module": "CommonJS",
|
||||||
"rootDir": "tests/",
|
"rootDir": "tests/",
|
||||||
"outDir": "build/",<% } %>
|
"outDir": "build/",
|
||||||
"types": ["<%= testingFramework %>"]
|
"types": ["<%= testRunner %>"]
|
||||||
},
|
},
|
||||||
"include": ["tests/**/*.ts"]
|
"include": ["tests/**/*.ts"]
|
||||||
}
|
}
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
require('@babel/register')({
|
|
||||||
extensions: ['.js', '.ts'],
|
|
||||||
presets: ['@babel/preset-env', '@babel/preset-typescript'],
|
|
||||||
});
|
|
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"spec_dir": "e2e",
|
"spec_dir": "e2e",
|
||||||
"spec_files": ["**/*[eE]2[eE].ts"],
|
"spec_files": ["**/*[eE]2[eE].js"],
|
||||||
"helpers": ["helpers/babel.js", "helpers/**/*.{js|ts}"],
|
"helpers": ["helpers/**/*.?(m)js"],
|
||||||
"env": {
|
"env": {
|
||||||
|
"failSpecWithNoExpectations": true,
|
||||||
"stopSpecOnExpectationFailure": false,
|
"stopSpecOnExpectationFailure": false,
|
||||||
"random": true
|
"random": true
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
* https://jestjs.io/docs/configuration
|
* https://jestjs.io/docs/configuration
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
/** @type {import('jest').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
testMatch: ['<rootDir>/tests/**/?(*.)+(e2e).[tj]s?(x)'],
|
testMatch: ['<rootDir>/tests/**/?(*.)+(e2e).js?(x)'],
|
||||||
preset: 'ts-jest',
|
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
file: ['e2e/babel.js'],
|
spec: './e2e/tests/**/*.e2e.js',
|
||||||
spec: './e2e/tests/**/*.e2e.ts',
|
|
||||||
};
|
};
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
require('@babel/register')({
|
|
||||||
extensions: ['.js', '.ts'],
|
|
||||||
presets: ['@babel/preset-env', '@babel/preset-typescript'],
|
|
||||||
});
|
|
@ -21,9 +21,9 @@ import {concatMap, map, scan} from 'rxjs/operators';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
addCommonFiles as addCommonFilesHelper,
|
addCommonFiles as addCommonFilesHelper,
|
||||||
addFilesSingle,
|
|
||||||
addFrameworkFiles,
|
addFrameworkFiles,
|
||||||
getNgCommandName,
|
getNgCommandName,
|
||||||
|
hasE2ETester,
|
||||||
} from '../utils/files.js';
|
} from '../utils/files.js';
|
||||||
import {getAngularConfig} from '../utils/json.js';
|
import {getAngularConfig} from '../utils/json.js';
|
||||||
import {
|
import {
|
||||||
@ -35,55 +35,24 @@ import {
|
|||||||
type NodePackage,
|
type NodePackage,
|
||||||
updateAngularJsonScripts,
|
updateAngularJsonScripts,
|
||||||
} from '../utils/packages.js';
|
} from '../utils/packages.js';
|
||||||
import {
|
import {TestRunner, type SchematicsOptions} from '../utils/types.js';
|
||||||
TestingFramework,
|
|
||||||
type SchematicsOptions,
|
const DEFAULT_PORT = 4200;
|
||||||
AngularProject,
|
|
||||||
} from '../utils/types.js';
|
|
||||||
|
|
||||||
// You don't have to export the function as default. You can also have more than one rule
|
// You don't have to export the function as default. You can also have more than one rule
|
||||||
// factory per file.
|
// factory per file.
|
||||||
export function ngAdd(userArgs: Record<string, string>): Rule {
|
export function ngAdd(options: SchematicsOptions): Rule {
|
||||||
const options = parseUserAddArgs(userArgs);
|
|
||||||
|
|
||||||
return (tree: Tree, context: SchematicContext) => {
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
return chain([
|
return chain([
|
||||||
addDependencies(options),
|
addDependencies(options),
|
||||||
addPuppeteerConfig(options),
|
|
||||||
addCommonFiles(options),
|
addCommonFiles(options),
|
||||||
addOtherFiles(options),
|
addOtherFiles(options),
|
||||||
updateScripts(options),
|
updateScripts(),
|
||||||
updateAngularConfig(options),
|
updateAngularConfig(options),
|
||||||
])(tree, context);
|
])(tree, context);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseUserAddArgs(userArgs: Record<string, string>): SchematicsOptions {
|
|
||||||
const options: Partial<SchematicsOptions> = {
|
|
||||||
...userArgs,
|
|
||||||
};
|
|
||||||
if ('p' in userArgs) {
|
|
||||||
options['port'] = Number(userArgs['p']);
|
|
||||||
}
|
|
||||||
if ('t' in userArgs) {
|
|
||||||
options['testingFramework'] = userArgs['t'] as TestingFramework;
|
|
||||||
}
|
|
||||||
if ('c' in userArgs) {
|
|
||||||
options['exportConfig'] =
|
|
||||||
typeof userArgs['c'] === 'string'
|
|
||||||
? userArgs['c'] === 'true'
|
|
||||||
: userArgs['c'];
|
|
||||||
}
|
|
||||||
if ('d' in userArgs) {
|
|
||||||
options['isDefaultTester'] =
|
|
||||||
typeof userArgs['d'] === 'string'
|
|
||||||
? userArgs['d'] === 'true'
|
|
||||||
: userArgs['d'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return options as SchematicsOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDependencies(options: SchematicsOptions): Rule {
|
function addDependencies(options: SchematicsOptions): Rule {
|
||||||
return (tree: Tree, context: SchematicContext) => {
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
context.logger.debug('Adding dependencies to "package.json"');
|
context.logger.debug('Adding dependencies to "package.json"');
|
||||||
@ -108,15 +77,15 @@ function addDependencies(options: SchematicsOptions): Rule {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateScripts(options: SchematicsOptions): Rule {
|
function updateScripts(): Rule {
|
||||||
return (tree: Tree, context: SchematicContext): Tree => {
|
return (tree: Tree, context: SchematicContext): Tree => {
|
||||||
context.logger.debug('Updating "package.json" scripts');
|
context.logger.debug('Updating "package.json" scripts');
|
||||||
const angularJson = getAngularConfig(tree);
|
const {projects} = getAngularConfig(tree);
|
||||||
const projects = Object.keys(angularJson['projects']);
|
const projectsKeys = Object.keys(projects);
|
||||||
|
|
||||||
if (projects.length === 1) {
|
if (projectsKeys.length === 1) {
|
||||||
const name = getNgCommandName(options);
|
const name = getNgCommandName(projects);
|
||||||
const prefix = options.isDefaultTester ? '' : `run ${projects[0]}:`;
|
const prefix = hasE2ETester(projects) ? `run ${projectsKeys[0]}:` : '';
|
||||||
return addPackageJsonScripts(tree, [
|
return addPackageJsonScripts(tree, [
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
@ -128,22 +97,6 @@ function updateScripts(options: SchematicsOptions): Rule {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPuppeteerConfig(options: SchematicsOptions): Rule {
|
|
||||||
return (tree: Tree, context: SchematicContext) => {
|
|
||||||
context.logger.debug('Adding Puppeteer config file.');
|
|
||||||
|
|
||||||
if (options.exportConfig) {
|
|
||||||
return addFilesSingle(tree, context, '', {root: ''} as AngularProject, {
|
|
||||||
options: options,
|
|
||||||
applyPath: './files/base',
|
|
||||||
relativeToWorkspacePath: `/`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function addCommonFiles(options: SchematicsOptions): Rule {
|
function addCommonFiles(options: SchematicsOptions): Rule {
|
||||||
return (tree: Tree, context: SchematicContext) => {
|
return (tree: Tree, context: SchematicContext) => {
|
||||||
context.logger.debug('Adding Puppeteer base files.');
|
context.logger.debug('Adding Puppeteer base files.');
|
||||||
@ -152,8 +105,8 @@ function addCommonFiles(options: SchematicsOptions): Rule {
|
|||||||
return addCommonFilesHelper(tree, context, projects, {
|
return addCommonFilesHelper(tree, context, projects, {
|
||||||
options: {
|
options: {
|
||||||
...options,
|
...options,
|
||||||
ext:
|
port: DEFAULT_PORT,
|
||||||
options.testingFramework === TestingFramework.Node ? 'test' : 'e2e',
|
ext: options.testRunner === TestRunner.Node ? 'test' : 'e2e',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -165,7 +118,10 @@ function addOtherFiles(options: SchematicsOptions): Rule {
|
|||||||
const {projects} = getAngularConfig(tree);
|
const {projects} = getAngularConfig(tree);
|
||||||
|
|
||||||
return addFrameworkFiles(tree, context, projects, {
|
return addFrameworkFiles(tree, context, projects, {
|
||||||
options,
|
options: {
|
||||||
|
...options,
|
||||||
|
port: DEFAULT_PORT,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,25 +4,13 @@
|
|||||||
"title": "Puppeteer Install Schema",
|
"title": "Puppeteer Install Schema",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"isDefaultTester": {
|
"testRunner": {
|
||||||
"type": "boolean",
|
|
||||||
"default": true,
|
|
||||||
"alias": "d",
|
|
||||||
"x-prompt": "Use Puppeteer as default `ng e2e` command?"
|
|
||||||
},
|
|
||||||
"exportConfig": {
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"alias": "c",
|
|
||||||
"x-prompt": "Export default Puppeteer config file?"
|
|
||||||
},
|
|
||||||
"testingFramework": {
|
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["jasmine", "jest", "mocha", "node"],
|
"enum": ["jasmine", "jest", "mocha", "node"],
|
||||||
"default": "jasmine",
|
"default": "jasmine",
|
||||||
"alias": "t",
|
"alias": "t",
|
||||||
"x-prompt": {
|
"x-prompt": {
|
||||||
"message": "With what Testing Library do you wish to integrate?",
|
"message": "Which test runners do you wish to use?",
|
||||||
"type": "list",
|
"type": "list",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
@ -43,12 +31,6 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"port": {
|
|
||||||
"type": ["number"],
|
|
||||||
"default": 4200,
|
|
||||||
"alias": "p",
|
|
||||||
"x-prompt": "On which port to spawn test server on?"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
@ -28,15 +28,16 @@ import {
|
|||||||
url,
|
url,
|
||||||
} from '@angular-devkit/schematics';
|
} from '@angular-devkit/schematics';
|
||||||
|
|
||||||
import {AngularProject, SchematicsOptions, TestingFramework} from './types.js';
|
import {AngularProject, SchematicsOptions, TestRunner} from './types.js';
|
||||||
|
|
||||||
export interface FilesOptions {
|
export interface FilesOptions {
|
||||||
options: {
|
options: {
|
||||||
testingFramework: TestingFramework;
|
testRunner: TestRunner;
|
||||||
port: number;
|
port: number;
|
||||||
name?: string;
|
name?: string;
|
||||||
exportConfig?: boolean;
|
exportConfig?: boolean;
|
||||||
ext?: string;
|
ext?: string;
|
||||||
|
route?: string;
|
||||||
};
|
};
|
||||||
applyPath: string;
|
applyPath: string;
|
||||||
relativeToWorkspacePath: string;
|
relativeToWorkspacePath: string;
|
||||||
@ -137,50 +138,41 @@ export function addFrameworkFiles(
|
|||||||
projects: Record<string, AngularProject>,
|
projects: Record<string, AngularProject>,
|
||||||
filesOptions: Omit<FilesOptions, 'applyPath' | 'relativeToWorkspacePath'>
|
filesOptions: Omit<FilesOptions, 'applyPath' | 'relativeToWorkspacePath'>
|
||||||
): any {
|
): any {
|
||||||
const testingFramework = filesOptions.options.testingFramework;
|
const testRunner = filesOptions.options.testRunner;
|
||||||
const options: FilesOptions = {
|
const options: FilesOptions = {
|
||||||
...filesOptions,
|
...filesOptions,
|
||||||
applyPath: `./files/${testingFramework}`,
|
applyPath: `./files/${testRunner}`,
|
||||||
relativeToWorkspacePath: `/`,
|
relativeToWorkspacePath: `/`,
|
||||||
};
|
};
|
||||||
|
|
||||||
return addFilesToProjects(tree, context, projects, options);
|
return addFilesToProjects(tree, context, projects, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getScriptFromOptions(
|
export function getScriptFromOptions(options: SchematicsOptions): string[][] {
|
||||||
options: SchematicsOptions,
|
switch (options.testRunner) {
|
||||||
root?: string
|
case TestRunner.Jasmine:
|
||||||
): string[][] {
|
return [[`jasmine`, '--config=./e2e/support/jasmine.json']];
|
||||||
let path = 'node_modules/.bin';
|
case TestRunner.Jest:
|
||||||
if (root && root !== '') {
|
return [[`jest`, '-c', 'e2e/jest.config.js']];
|
||||||
const nested = root
|
case TestRunner.Mocha:
|
||||||
.split('/')
|
return [[`mocha`, '--config=./e2e/.mocharc.js']];
|
||||||
.map(() => {
|
case TestRunner.Node:
|
||||||
return '../';
|
return [['node', '--test', '--test-reporter', 'spec', 'e2e/build/']];
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
path = `${nested}${path}`;
|
|
||||||
} else {
|
|
||||||
path = `./${path}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (options.testingFramework) {
|
|
||||||
case TestingFramework.Jasmine:
|
|
||||||
return [[`${path}/jasmine`, '--config=./e2e/support/jasmine.json']];
|
|
||||||
case TestingFramework.Jest:
|
|
||||||
return [[`${path}/jest`, '-c', 'e2e/jest.config.js']];
|
|
||||||
case TestingFramework.Mocha:
|
|
||||||
return [[`${path}/mocha`, '--config=./e2e/.mocharc.js']];
|
|
||||||
case TestingFramework.Node:
|
|
||||||
return [
|
|
||||||
[`${path}/tsc`, '-p', 'e2e/tsconfig.json'],
|
|
||||||
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNgCommandName(options: SchematicsOptions): string {
|
export function hasE2ETester(
|
||||||
if (options.isDefaultTester) {
|
projects: Record<string, AngularProject>
|
||||||
|
): boolean {
|
||||||
|
return Object.values(projects).some((project: AngularProject) => {
|
||||||
|
return Boolean(project.architect?.e2e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNgCommandName(
|
||||||
|
projects: Record<string, AngularProject>
|
||||||
|
): string {
|
||||||
|
if (!hasE2ETester(projects)) {
|
||||||
return 'e2e';
|
return 'e2e';
|
||||||
}
|
}
|
||||||
return 'puppeteer';
|
return 'puppeteer';
|
||||||
|
@ -24,7 +24,7 @@ import {
|
|||||||
getJsonFileAsObject,
|
getJsonFileAsObject,
|
||||||
getObjectAsJson,
|
getObjectAsJson,
|
||||||
} from './json.js';
|
} from './json.js';
|
||||||
import {SchematicsOptions, TestingFramework} from './types.js';
|
import {SchematicsOptions, TestRunner} from './types.js';
|
||||||
export interface NodePackage {
|
export interface NodePackage {
|
||||||
name: string;
|
name: string;
|
||||||
version: string;
|
version: string;
|
||||||
@ -115,24 +115,18 @@ export function getDependenciesFromOptions(
|
|||||||
options: SchematicsOptions
|
options: SchematicsOptions
|
||||||
): string[] {
|
): string[] {
|
||||||
const dependencies = ['puppeteer'];
|
const dependencies = ['puppeteer'];
|
||||||
const babelPackages = [
|
|
||||||
'@babel/core',
|
|
||||||
'@babel/register',
|
|
||||||
'@babel/preset-env',
|
|
||||||
'@babel/preset-typescript',
|
|
||||||
];
|
|
||||||
|
|
||||||
switch (options.testingFramework) {
|
switch (options.testRunner) {
|
||||||
case TestingFramework.Jasmine:
|
case TestRunner.Jasmine:
|
||||||
dependencies.push('jasmine', ...babelPackages);
|
dependencies.push('jasmine');
|
||||||
break;
|
break;
|
||||||
case TestingFramework.Jest:
|
case TestRunner.Jest:
|
||||||
dependencies.push('jest', '@types/jest', 'ts-jest');
|
dependencies.push('jest', '@types/jest');
|
||||||
break;
|
break;
|
||||||
case TestingFramework.Mocha:
|
case TestRunner.Mocha:
|
||||||
dependencies.push('mocha', '@types/mocha', ...babelPackages);
|
dependencies.push('mocha', '@types/mocha');
|
||||||
break;
|
break;
|
||||||
case TestingFramework.Node:
|
case TestRunner.Node:
|
||||||
dependencies.push('@types/node');
|
dependencies.push('@types/node');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -168,14 +162,10 @@ export function updateAngularJsonScripts(
|
|||||||
overwrite = true
|
overwrite = true
|
||||||
): Tree {
|
): Tree {
|
||||||
const angularJson = getAngularConfig(tree);
|
const angularJson = getAngularConfig(tree);
|
||||||
const name = getNgCommandName(options);
|
const name = getNgCommandName(angularJson.projects);
|
||||||
const port = options.port !== 4200 ? Number(options.port) : undefined;
|
|
||||||
|
|
||||||
Object.keys(angularJson['projects']).forEach(project => {
|
Object.keys(angularJson['projects']).forEach(project => {
|
||||||
const commands = getScriptFromOptions(
|
const commands = getScriptFromOptions(options);
|
||||||
options,
|
|
||||||
angularJson['projects'][project]!.root
|
|
||||||
);
|
|
||||||
const e2eScript = [
|
const e2eScript = [
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
@ -184,8 +174,7 @@ export function updateAngularJsonScripts(
|
|||||||
options: {
|
options: {
|
||||||
commands,
|
commands,
|
||||||
devServerTarget: `${project}:serve`,
|
devServerTarget: `${project}:serve`,
|
||||||
testingFramework: options.testingFramework,
|
testRunner: options.testRunner,
|
||||||
port,
|
|
||||||
},
|
},
|
||||||
configurations: {
|
configurations: {
|
||||||
production: {
|
production: {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export enum TestingFramework {
|
export enum TestRunner {
|
||||||
Jasmine = 'jasmine',
|
Jasmine = 'jasmine',
|
||||||
Jest = 'jest',
|
Jest = 'jest',
|
||||||
Mocha = 'mocha',
|
Mocha = 'mocha',
|
||||||
@ -22,15 +22,15 @@ export enum TestingFramework {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SchematicsOptions {
|
export interface SchematicsOptions {
|
||||||
isDefaultTester: boolean;
|
testRunner: TestRunner;
|
||||||
exportConfig: boolean;
|
|
||||||
testingFramework: TestingFramework;
|
|
||||||
port: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PuppeteerSchematicsConfig {
|
export interface PuppeteerSchematicsConfig {
|
||||||
builder: string;
|
builder: string;
|
||||||
options: SchematicsOptions;
|
options: {
|
||||||
|
port: number;
|
||||||
|
testRunner: TestRunner;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
export interface AngularProject {
|
export interface AngularProject {
|
||||||
root: string;
|
root: string;
|
||||||
@ -46,4 +46,5 @@ export interface AngularJson {
|
|||||||
export interface SchematicsSpec {
|
export interface SchematicsSpec {
|
||||||
name: string;
|
name: string;
|
||||||
project?: string;
|
project?: string;
|
||||||
|
route?: string;
|
||||||
}
|
}
|
||||||
|
26
packages/ng-schematics/test/src/config.spec.ts
Normal file
26
packages/ng-schematics/test/src/config.spec.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import expect from 'expect';
|
||||||
|
|
||||||
|
import {
|
||||||
|
buildTestingTree,
|
||||||
|
getMultiProjectFile,
|
||||||
|
setupHttpHooks,
|
||||||
|
} from './utils.js';
|
||||||
|
|
||||||
|
describe('@puppeteer/ng-schematics: config', () => {
|
||||||
|
setupHttpHooks();
|
||||||
|
|
||||||
|
describe('Single Project', () => {
|
||||||
|
it('should create default file', async () => {
|
||||||
|
const tree = await buildTestingTree('config', 'single');
|
||||||
|
expect(tree.files).toContain('/.puppeteerrc.mjs');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Multi projects', () => {
|
||||||
|
it('should create default file', async () => {
|
||||||
|
const tree = await buildTestingTree('config', 'multi');
|
||||||
|
expect(tree.files).toContain('/.puppeteerrc.mjs');
|
||||||
|
expect(tree.files).not.toContain(getMultiProjectFile('.puppeteerrc.mjs'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -6,12 +6,12 @@ import {
|
|||||||
setupHttpHooks,
|
setupHttpHooks,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
|
|
||||||
describe('@puppeteer/ng-schematics: test', () => {
|
describe('@puppeteer/ng-schematics: e2e', () => {
|
||||||
setupHttpHooks();
|
setupHttpHooks();
|
||||||
|
|
||||||
describe('Single Project', () => {
|
describe('Single Project', () => {
|
||||||
it('should create default file', async () => {
|
it('should create default file', async () => {
|
||||||
const tree = await buildTestingTree('test', 'single', {
|
const tree = await buildTestingTree('e2e', 'single', {
|
||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
});
|
});
|
||||||
expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts');
|
expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts');
|
||||||
@ -19,9 +19,9 @@ describe('@puppeteer/ng-schematics: test', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create Node file', async () => {
|
it('should create Node file', async () => {
|
||||||
const tree = await buildTestingTree('test', 'single', {
|
const tree = await buildTestingTree('e2e', 'single', {
|
||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
testingFramework: 'node',
|
testRunner: 'node',
|
||||||
});
|
});
|
||||||
expect(tree.files).not.toContain('/e2e/tests/my-test.e2e.ts');
|
expect(tree.files).not.toContain('/e2e/tests/my-test.e2e.ts');
|
||||||
expect(tree.files).toContain('/e2e/tests/my-test.test.ts');
|
expect(tree.files).toContain('/e2e/tests/my-test.test.ts');
|
||||||
@ -30,7 +30,7 @@ describe('@puppeteer/ng-schematics: test', () => {
|
|||||||
|
|
||||||
describe('Multi projects', () => {
|
describe('Multi projects', () => {
|
||||||
it('should create default file', async () => {
|
it('should create default file', async () => {
|
||||||
const tree = await buildTestingTree('test', 'multi', {
|
const tree = await buildTestingTree('e2e', 'multi', {
|
||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
});
|
});
|
||||||
expect(tree.files).toContain(
|
expect(tree.files).toContain(
|
||||||
@ -42,9 +42,9 @@ describe('@puppeteer/ng-schematics: test', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should create Node file', async () => {
|
it('should create Node file', async () => {
|
||||||
const tree = await buildTestingTree('test', 'multi', {
|
const tree = await buildTestingTree('e2e', 'multi', {
|
||||||
name: 'myTest',
|
name: 'myTest',
|
||||||
testingFramework: 'node',
|
testRunner: 'node',
|
||||||
});
|
});
|
||||||
expect(tree.files).not.toContain(
|
expect(tree.files).not.toContain(
|
||||||
getMultiProjectFile('e2e/tests/my-test.e2e.ts')
|
getMultiProjectFile('e2e/tests/my-test.e2e.ts')
|
@ -5,6 +5,7 @@ import {
|
|||||||
getAngularJsonScripts,
|
getAngularJsonScripts,
|
||||||
getMultiProjectFile,
|
getMultiProjectFile,
|
||||||
getPackageJson,
|
getPackageJson,
|
||||||
|
runSchematic,
|
||||||
setupHttpHooks,
|
setupHttpHooks,
|
||||||
} from './utils.js';
|
} from './utils.js';
|
||||||
|
|
||||||
@ -30,49 +31,36 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should update create proper "ng" command for non default tester', async () => {
|
it('should update create proper "ng" command for non default tester', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
let tree = await buildTestingTree('ng-add', 'single');
|
||||||
isDefaultTester: false,
|
// Re-run schematic to have e2e populated
|
||||||
});
|
tree = await runSchematic(tree, 'ng-add');
|
||||||
const {scripts} = getPackageJson(tree);
|
const {scripts} = getPackageJson(tree);
|
||||||
const {builder} = getAngularJsonScripts(tree, false);
|
const {builder} = getAngularJsonScripts(tree, false);
|
||||||
|
|
||||||
expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer');
|
expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer');
|
||||||
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
||||||
});
|
});
|
||||||
it('should create Puppeteer config', async () => {
|
|
||||||
const {files} = await buildTestingTree('ng-add', 'single', {
|
|
||||||
exportConfig: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(files).toContain('/.puppeteerrc.cjs');
|
|
||||||
});
|
|
||||||
it('should not create Puppeteer config', async () => {
|
it('should not create Puppeteer config', async () => {
|
||||||
const {files} = await buildTestingTree('ng-add', 'single', {
|
const {files} = await buildTestingTree('ng-add', 'single');
|
||||||
exportConfig: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(files).not.toContain('/.puppeteerrc.cjs');
|
expect(files).not.toContain('/.puppeteerrc.cjs');
|
||||||
});
|
});
|
||||||
it('should create Jasmine files and update "package.json"', async () => {
|
it('should create Jasmine files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
const tree = await buildTestingTree('ng-add', 'single', {
|
||||||
testingFramework: 'jasmine',
|
testRunner: 'jasmine',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain('/e2e/support/jasmine.json');
|
expect(tree.files).toContain('/e2e/support/jasmine.json');
|
||||||
expect(tree.files).toContain('/e2e/helpers/babel.js');
|
|
||||||
expect(devDependencies).toContain('jasmine');
|
expect(devDependencies).toContain('jasmine');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
|
||||||
expect(devDependencies).toContain('@babel/register');
|
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`./node_modules/.bin/jasmine`, '--config=./e2e/support/jasmine.json'],
|
[`jasmine`, '--config=./e2e/support/jasmine.json'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Jest files and update "package.json"', async () => {
|
it('should create Jest files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
const tree = await buildTestingTree('ng-add', 'single', {
|
||||||
testingFramework: 'jest',
|
testRunner: 'jest',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
@ -80,32 +68,27 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
expect(tree.files).toContain('/e2e/jest.config.js');
|
expect(tree.files).toContain('/e2e/jest.config.js');
|
||||||
expect(devDependencies).toContain('jest');
|
expect(devDependencies).toContain('jest');
|
||||||
expect(devDependencies).toContain('@types/jest');
|
expect(devDependencies).toContain('@types/jest');
|
||||||
expect(devDependencies).toContain('ts-jest');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`./node_modules/.bin/jest`, '-c', 'e2e/jest.config.js'],
|
[`jest`, '-c', 'e2e/jest.config.js'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Mocha files and update "package.json"', async () => {
|
it('should create Mocha files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
const tree = await buildTestingTree('ng-add', 'single', {
|
||||||
testingFramework: 'mocha',
|
testRunner: 'mocha',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain('/e2e/.mocharc.js');
|
expect(tree.files).toContain('/e2e/.mocharc.js');
|
||||||
expect(tree.files).toContain('/e2e/babel.js');
|
|
||||||
expect(devDependencies).toContain('mocha');
|
expect(devDependencies).toContain('mocha');
|
||||||
expect(devDependencies).toContain('@types/mocha');
|
expect(devDependencies).toContain('@types/mocha');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
|
||||||
expect(devDependencies).toContain('@babel/register');
|
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`./node_modules/.bin/mocha`, '--config=./e2e/.mocharc.js'],
|
[`mocha`, '--config=./e2e/.mocharc.js'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Node files', async () => {
|
it('should create Node files', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
const tree = await buildTestingTree('ng-add', 'single', {
|
||||||
testingFramework: 'node',
|
testRunner: 'node',
|
||||||
});
|
});
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
@ -113,25 +96,15 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
expect(tree.files).not.toContain('/e2e/tests/app.e2e.ts');
|
expect(tree.files).not.toContain('/e2e/tests/app.e2e.ts');
|
||||||
expect(tree.files).toContain('/e2e/tests/app.test.ts');
|
expect(tree.files).toContain('/e2e/tests/app.test.ts');
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`./node_modules/.bin/tsc`, '-p', 'e2e/tsconfig.json'],
|
|
||||||
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should not create port option', async () => {
|
it('should not create port value', async () => {
|
||||||
const tree = await buildTestingTree('ng-add');
|
const tree = await buildTestingTree('ng-add');
|
||||||
|
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
expect(options['port']).toBeUndefined();
|
expect(options['port']).toBeUndefined();
|
||||||
});
|
});
|
||||||
it('should create port option when specified', async () => {
|
|
||||||
const port = 8080;
|
|
||||||
const tree = await buildTestingTree('ng-add', 'single', {
|
|
||||||
port,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {options} = getAngularJsonScripts(tree);
|
|
||||||
expect(options['port']).toBe(port);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Multi projects', () => {
|
describe('Multi projects', () => {
|
||||||
@ -153,33 +126,24 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should update create proper "ng" command for non default tester', async () => {
|
it('should update create proper "ng" command for non default tester', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
let tree = await buildTestingTree('ng-add', 'multi');
|
||||||
isDefaultTester: false,
|
// Re-run schematic to have e2e populated
|
||||||
});
|
tree = await runSchematic(tree, 'ng-add');
|
||||||
const {scripts} = getPackageJson(tree);
|
const {scripts} = getPackageJson(tree);
|
||||||
const {builder} = getAngularJsonScripts(tree, false);
|
const {builder} = getAngularJsonScripts(tree, false);
|
||||||
|
|
||||||
expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer');
|
expect(scripts['puppeteer']).toBe('ng run sandbox:puppeteer');
|
||||||
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
expect(builder).toBe('@puppeteer/ng-schematics:puppeteer');
|
||||||
});
|
});
|
||||||
it('should create Puppeteer config', async () => {
|
|
||||||
const {files} = await buildTestingTree('ng-add', 'multi', {
|
|
||||||
exportConfig: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(files).toContain('/.puppeteerrc.cjs');
|
|
||||||
});
|
|
||||||
it('should not create Puppeteer config', async () => {
|
it('should not create Puppeteer config', async () => {
|
||||||
const {files} = await buildTestingTree('ng-add', 'multi', {
|
const {files} = await buildTestingTree('ng-add', 'multi');
|
||||||
exportConfig: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(files).not.toContain(getMultiProjectFile('.puppeteerrc.cjs'));
|
expect(files).not.toContain(getMultiProjectFile('.puppeteerrc.cjs'));
|
||||||
expect(files).not.toContain('/.puppeteerrc.cjs');
|
expect(files).not.toContain('/.puppeteerrc.cjs');
|
||||||
});
|
});
|
||||||
it('should create Jasmine files and update "package.json"', async () => {
|
it('should create Jasmine files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
const tree = await buildTestingTree('ng-add', 'multi', {
|
||||||
testingFramework: 'jasmine',
|
testRunner: 'jasmine',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
@ -187,21 +151,14 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
expect(tree.files).toContain(
|
expect(tree.files).toContain(
|
||||||
getMultiProjectFile('e2e/support/jasmine.json')
|
getMultiProjectFile('e2e/support/jasmine.json')
|
||||||
);
|
);
|
||||||
expect(tree.files).toContain(getMultiProjectFile('e2e/helpers/babel.js'));
|
|
||||||
expect(devDependencies).toContain('jasmine');
|
expect(devDependencies).toContain('jasmine');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
|
||||||
expect(devDependencies).toContain('@babel/register');
|
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[
|
[`jasmine`, '--config=./e2e/support/jasmine.json'],
|
||||||
`../../node_modules/.bin/jasmine`,
|
|
||||||
'--config=./e2e/support/jasmine.json',
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Jest files and update "package.json"', async () => {
|
it('should create Jest files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
const tree = await buildTestingTree('ng-add', 'multi', {
|
||||||
testingFramework: 'jest',
|
testRunner: 'jest',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
@ -209,32 +166,27 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
expect(tree.files).toContain(getMultiProjectFile('e2e/jest.config.js'));
|
expect(tree.files).toContain(getMultiProjectFile('e2e/jest.config.js'));
|
||||||
expect(devDependencies).toContain('jest');
|
expect(devDependencies).toContain('jest');
|
||||||
expect(devDependencies).toContain('@types/jest');
|
expect(devDependencies).toContain('@types/jest');
|
||||||
expect(devDependencies).toContain('ts-jest');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`../../node_modules/.bin/jest`, '-c', 'e2e/jest.config.js'],
|
[`jest`, '-c', 'e2e/jest.config.js'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Mocha files and update "package.json"', async () => {
|
it('should create Mocha files and update "package.json"', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
const tree = await buildTestingTree('ng-add', 'multi', {
|
||||||
testingFramework: 'mocha',
|
testRunner: 'mocha',
|
||||||
});
|
});
|
||||||
const {devDependencies} = getPackageJson(tree);
|
const {devDependencies} = getPackageJson(tree);
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
expect(tree.files).toContain(getMultiProjectFile('e2e/.mocharc.js'));
|
expect(tree.files).toContain(getMultiProjectFile('e2e/.mocharc.js'));
|
||||||
expect(tree.files).toContain(getMultiProjectFile('e2e/babel.js'));
|
|
||||||
expect(devDependencies).toContain('mocha');
|
expect(devDependencies).toContain('mocha');
|
||||||
expect(devDependencies).toContain('@types/mocha');
|
expect(devDependencies).toContain('@types/mocha');
|
||||||
expect(devDependencies).toContain('@babel/core');
|
|
||||||
expect(devDependencies).toContain('@babel/register');
|
|
||||||
expect(devDependencies).toContain('@babel/preset-typescript');
|
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`../../node_modules/.bin/mocha`, '--config=./e2e/.mocharc.js'],
|
[`mocha`, '--config=./e2e/.mocharc.js'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should create Node files', async () => {
|
it('should create Node files', async () => {
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
const tree = await buildTestingTree('ng-add', 'multi', {
|
||||||
testingFramework: 'node',
|
testRunner: 'node',
|
||||||
});
|
});
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
|
|
||||||
@ -246,24 +198,14 @@ describe('@puppeteer/ng-schematics: ng-add', () => {
|
|||||||
getMultiProjectFile('e2e/tests/app.test.ts')
|
getMultiProjectFile('e2e/tests/app.test.ts')
|
||||||
);
|
);
|
||||||
expect(options['commands']).toEqual([
|
expect(options['commands']).toEqual([
|
||||||
[`../../node_modules/.bin/tsc`, '-p', 'e2e/tsconfig.json'],
|
|
||||||
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
['node', '--test', '--test-reporter', 'spec', 'e2e/build/'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
it('should not create port option', async () => {
|
it('should not create port value', async () => {
|
||||||
const tree = await buildTestingTree('ng-add');
|
const tree = await buildTestingTree('ng-add');
|
||||||
|
|
||||||
const {options} = getAngularJsonScripts(tree);
|
const {options} = getAngularJsonScripts(tree);
|
||||||
expect(options['port']).toBeUndefined();
|
expect(options['port']).toBeUndefined();
|
||||||
});
|
});
|
||||||
it('should create port option when specified', async () => {
|
|
||||||
const port = 8080;
|
|
||||||
const tree = await buildTestingTree('ng-add', 'multi', {
|
|
||||||
port,
|
|
||||||
});
|
|
||||||
|
|
||||||
const {options} = getAngularJsonScripts(tree);
|
|
||||||
expect(options['port']).toBe(port);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -74,7 +74,7 @@ export function getMultiProjectFile(file: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function buildTestingTree(
|
export async function buildTestingTree(
|
||||||
command: 'ng-add' | 'test',
|
command: 'ng-add' | 'e2e' | 'config',
|
||||||
type: 'single' | 'multi' = 'single',
|
type: 'single' | 'multi' = 'single',
|
||||||
userOptions?: Record<string, any>
|
userOptions?: Record<string, any>
|
||||||
): Promise<UnitTestTree> {
|
): Promise<UnitTestTree> {
|
||||||
@ -83,9 +83,7 @@ export async function buildTestingTree(
|
|||||||
join(__dirname, '../../lib/schematics/collection.json')
|
join(__dirname, '../../lib/schematics/collection.json')
|
||||||
);
|
);
|
||||||
const options = {
|
const options = {
|
||||||
isDefaultTester: true,
|
testRunner: 'jasmine',
|
||||||
exportConfig: false,
|
|
||||||
testingFramework: 'jasmine',
|
|
||||||
...userOptions,
|
...userOptions,
|
||||||
};
|
};
|
||||||
let workingTree: UnitTestTree;
|
let workingTree: UnitTestTree;
|
||||||
@ -121,3 +119,15 @@ export async function buildTestingTree(
|
|||||||
|
|
||||||
return await runner.runSchematic(command, 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);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user