fix: update documentation for ng-schematics (#11533)

This commit is contained in:
Nikolay Vitkov 2023-12-13 13:32:17 +01:00 committed by GitHub
parent bfdba04bd2
commit 744e8944ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1180 additions and 1482 deletions

View File

@ -40,7 +40,7 @@ When adding schematics to your project you can to provide following options:
Puppeteer Angular Schematic exposes a method to create a single test file. Puppeteer Angular Schematic exposes a method to create a single test file.
```bash ```bash
ng generate @puppeteer/ng-schematics:test "<TestName>" ng generate @puppeteer/ng-schematics:e2e "<TestName>"
``` ```
### Running test server and dev server at the same time ### Running test server and dev server at the same time
@ -73,32 +73,12 @@ const baseUrl = 'http://localhost:8080';
Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo. Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo.
### Sandbox ### Sandbox smoke tests
For easier development we provide a script to auto-generate the Angular project to test against. Simply run: To make integration easier smoke test can be run with a single command, that will create a fresh install of Angular (single application and a milti application projects). Then it will install the schematics inside them and run the initial e2e tests:
```bash ```bash
npm run sandbox -- --init node tools/smoke.mjs
```
After that to run `@puppeteer/ng-schematics` against the Sandbox Angular project run:
```bash
npm run sandbox
# or to auto-build and then run schematics
npm run sandbox -- --build
```
To run the creating of single test schematic:
```bash
npm run sandbox:test
```
To create a multi project workspace use the following command
```bash
npm run sandbox -- --init --multi
``` ```
### Unit Testing ### Unit Testing
@ -111,28 +91,52 @@ npm run test
## Migrating from Protractor ## Migrating from Protractor
### Browser ### Entry point
Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes different API compared to the one exposed by Protractor. Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes the browser process.
A more closes comparison for Protractor's `browser` would be Puppeteer's [`page`](https://pptr.dev/api/puppeteer.page).
```ts ```ts
import puppeteer from 'puppeteer'; // Testing framework specific imports
(async () => { import {setupBrowserHooks, getBrowserState} from './utils';
const browser = await puppeteer.launch();
it('should work', () => {
const page = await browser.newPage();
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements // Query elements
const element = await page.$('my-component'); await page
.locator('my-component')
// Do actions // Click on the element once found
await element.click(); .click();
}); });
});
```
await browser.close(); ### Getting element properties
})();
You can easily get any property of the element.
```ts
// Testing framework specific imports
import {setupBrowserHooks, getBrowserState} from './utils';
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements
const elementText = await page
.locator('.my-component')
.map(button => button.innerText)
// Wait for element to show up
.wait();
// Assert via assertion library
});
});
``` ```
### Query Selectors ### Query Selectors
@ -154,3 +158,73 @@ The following table shows Puppeteer's equivalents to [Protractor By](https://www
| JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` | | JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` |
> For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors). > For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors).
### Actions Selectors
Puppeteer allows you to all necessary actions to allow test your application.
```ts
// Click on the element.
element(locator).click();
// Puppeteer equivalent
await page.locator(locator).click();
// Send keys to the element (usually an input).
element(locator).sendKeys('my text');
// Puppeteer equivalent
await page.locator(locator).fill('my text');
// Clear the text in an element (usually an input).
element(locator).clear();
// Puppeteer equivalent
await page.locator(locator).fill('');
// Get the value of an attribute, for example, get the value of an input.
element(locator).getAttribute('value');
// Puppeteer equivalent
const element = await page.locator(locator).waitHandle();
const value = await element.getProperty('value');
```
### Example
Sample Protractor test:
```ts
describe('Protractor Demo', function () {
it('should add one and two', function () {
browser.get('http://juliemr.github.io/protractor-demo/');
element(by.model('first')).sendKeys(1);
element(by.model('second')).sendKeys(2);
element(by.id('gobutton')).click();
expect(element(by.binding('latest')).getText()).toEqual('3');
});
});
```
Sample Puppeteer migration:
```ts
import {setupBrowserHooks, getBrowserState} from './utils';
describe('Puppeteer Demo', function () {
setupBrowserHooks();
it('should add one and two', function () {
const {page} = getBrowserState();
await page.goto('http://juliemr.github.io/protractor-demo/');
await page.locator('.form-inline > input:nth-child(1)').fill('1');
await page.locator('.form-inline > input:nth-child(2)').fill('2');
await page.locator('#gobutton').fill('2');
const result = await page
.locator('.table tbody td:last-of-type')
.map(header => header.innerText)
.wait();
expect(result).toEqual('3');
});
});
```

2178
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,3 @@
# Sandbox # Sandbox
sandbox/ sandbox/
multi/

View File

@ -40,7 +40,7 @@ When adding schematics to your project you can to provide following options:
Puppeteer Angular Schematic exposes a method to create a single test file. Puppeteer Angular Schematic exposes a method to create a single test file.
```bash ```bash
ng generate @puppeteer/ng-schematics:test "<TestName>" ng generate @puppeteer/ng-schematics:e2e "<TestName>"
``` ```
### Running test server and dev server at the same time ### Running test server and dev server at the same time
@ -73,32 +73,12 @@ const baseUrl = 'http://localhost:8080';
Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo. Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo.
### Sandbox ### Sandbox smoke tests
For easier development we provide a script to auto-generate the Angular project to test against. Simply run: To make integration easier smoke test can be run with a single command, that will create a fresh install of Angular (single application and a milti application projects). Then it will install the schematics inside them and run the initial e2e tests:
```bash ```bash
npm run sandbox -- --init node tools/smoke.mjs
```
After that to run `@puppeteer/ng-schematics` against the Sandbox Angular project run:
```bash
npm run sandbox
# or to auto-build and then run schematics
npm run sandbox -- --build
```
To run the creating of single test schematic:
```bash
npm run sandbox:test
```
To create a multi project workspace use the following command
```bash
npm run sandbox -- --init --multi
``` ```
### Unit Testing ### Unit Testing
@ -111,28 +91,52 @@ npm run test
## Migrating from Protractor ## Migrating from Protractor
### Browser ### Entry point
Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes different API compared to the one exposed by Protractor. Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes the browser process.
A more closes comparison for Protractor's `browser` would be Puppeteer's [`page`](https://pptr.dev/api/puppeteer.page).
```ts ```ts
import puppeteer from 'puppeteer'; // Testing framework specific imports
(async () => { import {setupBrowserHooks, getBrowserState} from './utils';
const browser = await puppeteer.launch();
it('should work', () => {
const page = await browser.newPage();
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements // Query elements
const element = await page.$('my-component'); await page
.locator('my-component')
// Do actions // Click on the element once found
await element.click(); .click();
}); });
});
```
await browser.close(); ### Getting element properties
})();
You can easily get any property of the element.
```ts
// Testing framework specific imports
import {setupBrowserHooks, getBrowserState} from './utils';
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements
const elementText = await page
.locator('.my-component')
.map(button => button.innerText)
// Wait for element to show up
.wait();
// Assert via assertion library
});
});
``` ```
### Query Selectors ### Query Selectors
@ -154,3 +158,73 @@ The following table shows Puppeteer's equivalents to [Protractor By](https://www
| JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` | | JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` |
> For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors). > For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors).
### Actions Selectors
Puppeteer allows you to all necessary actions to allow test your application.
```ts
// Click on the element.
element(locator).click();
// Puppeteer equivalent
await page.locator(locator).click();
// Send keys to the element (usually an input).
element(locator).sendKeys('my text');
// Puppeteer equivalent
await page.locator(locator).fill('my text');
// Clear the text in an element (usually an input).
element(locator).clear();
// Puppeteer equivalent
await page.locator(locator).fill('');
// Get the value of an attribute, for example, get the value of an input.
element(locator).getAttribute('value');
// Puppeteer equivalent
const element = await page.locator(locator).waitHandle();
const value = await element.getProperty('value');
```
### Example
Sample Protractor test:
```ts
describe('Protractor Demo', function () {
it('should add one and two', function () {
browser.get('http://juliemr.github.io/protractor-demo/');
element(by.model('first')).sendKeys(1);
element(by.model('second')).sendKeys(2);
element(by.id('gobutton')).click();
expect(element(by.binding('latest')).getText()).toEqual('3');
});
});
```
Sample Puppeteer migration:
```ts
import {setupBrowserHooks, getBrowserState} from './utils';
describe('Puppeteer Demo', function () {
setupBrowserHooks();
it('should add one and two', function () {
const {page} = getBrowserState();
await page.goto('http://juliemr.github.io/protractor-demo/');
await page.locator('.form-inline > input:nth-child(1)').fill('1');
await page.locator('.form-inline > input:nth-child(2)').fill('2');
await page.locator('#gobutton').fill('2');
const result = await page
.locator('.table tbody td:last-of-type')
.map(header => header.innerText)
.wait();
expect(result).toEqual('3');
});
});
```

View File

@ -56,14 +56,14 @@
"node": ">=16.13.2" "node": ">=16.13.2"
}, },
"dependencies": { "dependencies": {
"@angular-devkit/architect": "^0.1602.10", "@angular-devkit/architect": "^0.1700.6",
"@angular-devkit/core": "^16.2.10", "@angular-devkit/core": "^17.0.6",
"@angular-devkit/schematics": "^16.2.10" "@angular-devkit/schematics": "^17.0.6"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.18.61", "@types/node": "^16.18.61",
"@schematics/angular": "^16.2.10", "@schematics/angular": "^17.0.6",
"@angular/cli": "^16.2.10", "@angular/cli": "^17.0.6",
"rxjs": "7.8.1" "rxjs": "7.8.1"
}, },
"files": [ "files": [

View File

@ -55,8 +55,8 @@ function parseUserTestArgs(userArgs: Record<string, string>): SchematicsSpec {
options['route'] = userArgs['r']; options['route'] = userArgs['r'];
} }
if (options['route'] && !options['route'].startsWith('/')) { if (options['route'] && options['route'].startsWith('/')) {
options['route'] = `/${options['route']}`; options['route'] = options['route'].substring(1);
} }
return options as SchematicsSpec; return options as SchematicsSpec;

View File

@ -10,8 +10,7 @@ describe('App test', function () {
setupBrowserHooks(); setupBrowserHooks();
it('is running', async function () { it('is running', async function () {
const {page} = getBrowserState(); const {page} = getBrowserState();
const element = await page.waitForSelector('text/<%= project %>'); const element = await page.locator('::-p-text(<%= project %>)').wait();
<% if(testRunner == 'jasmine' || testRunner == 'jest') { %> <% if(testRunner == 'jasmine' || testRunner == 'jest') { %>
expect(element).not.toBeNull(); expect(element).not.toBeNull();
<% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %> <% } %><% if(testRunner == 'mocha' || testRunner == 'node') { %>

View File

@ -7,7 +7,7 @@ const baseUrl = process.env['baseUrl'] ?? '<%= baseUrl %>';
let browser: puppeteer.Browser; let browser: puppeteer.Browser;
let page: puppeteer.Page; let page: puppeteer.Page;
export function setupBrowserHooks(path = '/'): void { export function setupBrowserHooks(path = ''): void {
<% if(testRunner == 'jasmine' || testRunner == 'jest') { %> <% if(testRunner == 'jasmine' || testRunner == 'jest') { %>
beforeAll(async () => { beforeAll(async () => {
browser = await puppeteer.launch({ browser = await puppeteer.launch({

View File

@ -107,7 +107,7 @@ function getProjectBaseUrl(project: any, port: number): string {
options.protocol = projectOptions.ssl ? 'https' : 'http'; options.protocol = projectOptions.ssl ? 'https' : 'http';
} }
return `${options.protocol}://${options.host}:${options.port}`; return `${options.protocol}://${options.host}:${options.port}/`;
} }
function getTsConfigPath(project: AngularProject): string { function getTsConfigPath(project: AngularProject): string {

View File

@ -35,7 +35,7 @@ describe('@puppeteer/ng-schematics: e2e', () => {
}); });
expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts');
expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain( expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain(
`setupBrowserHooks('/${route}');` `setupBrowserHooks('${route}');`
); );
}); });
@ -47,7 +47,7 @@ describe('@puppeteer/ng-schematics: e2e', () => {
}); });
expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts'); expect(tree.files).toContain('/e2e/tests/my-test.e2e.ts');
expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain( expect(tree.readContent('/e2e/tests/my-test.e2e.ts')).toContain(
`setupBrowserHooks('${route}');` `setupBrowserHooks('home');`
); );
}); });
}); });
@ -89,7 +89,7 @@ describe('@puppeteer/ng-schematics: e2e', () => {
); );
expect( expect(
tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts')) tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts'))
).toContain(`setupBrowserHooks('/${route}');`); ).toContain(`setupBrowserHooks('${route}');`);
}); });
it('should create with route with starting slash', async () => { it('should create with route with starting slash', async () => {
@ -103,7 +103,7 @@ describe('@puppeteer/ng-schematics: e2e', () => {
); );
expect( expect(
tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts')) tree.readContent(getMultiApplicationFile('e2e/tests/my-test.e2e.ts'))
).toContain(`setupBrowserHooks('${route}');`); ).toContain(`setupBrowserHooks('home');`);
}); });
}); });
}); });

View File

@ -9,15 +9,17 @@ if (process.env.CI) {
await Promise.all([ await Promise.all([
runNgSchematicsSandbox({ runNgSchematicsSandbox({
isMulti: false,
isInit: true, isInit: true,
}), }),
runNgSchematicsSandbox({ runNgSchematicsSandbox({
isInit: true,
isMulti: true, isMulti: true,
isInit: true,
}), }),
]); ]);
await runNgSchematicsSandbox({ await runNgSchematicsSandbox({
isMulti: false,
isSmoke: true, isSmoke: true,
}); });

View File

@ -40,7 +40,7 @@ When adding schematics to your project you can to provide following options:
Puppeteer Angular Schematic exposes a method to create a single test file. Puppeteer Angular Schematic exposes a method to create a single test file.
```bash ```bash
ng generate @puppeteer/ng-schematics:test "<TestName>" ng generate @puppeteer/ng-schematics:e2e "<TestName>"
``` ```
### Running test server and dev server at the same time ### Running test server and dev server at the same time
@ -73,32 +73,12 @@ const baseUrl = 'http://localhost:8080';
Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo. Check out our [contributing guide](https://pptr.dev/contributing) to get an overview of what you need to develop in the Puppeteer repo.
### Sandbox ### Sandbox smoke tests
For easier development we provide a script to auto-generate the Angular project to test against. Simply run: To make integration easier smoke test can be run with a single command, that will create a fresh install of Angular (single application and a milti application projects). Then it will install the schematics inside them and run the initial e2e tests:
```bash ```bash
npm run sandbox -- --init node tools/smoke.mjs
```
After that to run `@puppeteer/ng-schematics` against the Sandbox Angular project run:
```bash
npm run sandbox
# or to auto-build and then run schematics
npm run sandbox -- --build
```
To run the creating of single test schematic:
```bash
npm run sandbox:test
```
To create a multi project workspace use the following command
```bash
npm run sandbox -- --init --multi
``` ```
### Unit Testing ### Unit Testing
@ -111,28 +91,52 @@ npm run test
## Migrating from Protractor ## Migrating from Protractor
### Browser ### Entry point
Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes different API compared to the one exposed by Protractor. Puppeteer has its own [`browser`](https://pptr.dev/api/puppeteer.browser) that exposes the browser process.
A more closes comparison for Protractor's `browser` would be Puppeteer's [`page`](https://pptr.dev/api/puppeteer.page).
```ts ```ts
import puppeteer from 'puppeteer'; // Testing framework specific imports
(async () => { import {setupBrowserHooks, getBrowserState} from './utils';
const browser = await puppeteer.launch();
it('should work', () => {
const page = await browser.newPage();
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements // Query elements
const element = await page.$('my-component'); await page
.locator('my-component')
// Do actions // Click on the element once found
await element.click(); .click();
}); });
});
```
await browser.close(); ### Getting element properties
})();
You can easily get any property of the element.
```ts
// Testing framework specific imports
import {setupBrowserHooks, getBrowserState} from './utils';
describe('<Test Name>', function () {
setupBrowserHooks();
it('is running', async function () {
const {page} = getBrowserState();
// Query elements
const elementText = await page
.locator('.my-component')
.map(button => button.innerText)
// Wait for element to show up
.wait();
// Assert via assertion library
});
});
``` ```
### Query Selectors ### Query Selectors
@ -154,3 +158,73 @@ The following table shows Puppeteer's equivalents to [Protractor By](https://www
| JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` | | JS | `$(by.js('document.querySelector("<CSS>")'))` | `page.evaluateHandle(() => document.querySelector('<CSS>'))` |
> For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors). > For advanced use cases such as Protractor's `by.addLocator` you can check Puppeteer's [Custom selectors](https://pptr.dev/guides/query-selectors#custom-selectors).
### Actions Selectors
Puppeteer allows you to all necessary actions to allow test your application.
```ts
// Click on the element.
element(locator).click();
// Puppeteer equivalent
await page.locator(locator).click();
// Send keys to the element (usually an input).
element(locator).sendKeys('my text');
// Puppeteer equivalent
await page.locator(locator).fill('my text');
// Clear the text in an element (usually an input).
element(locator).clear();
// Puppeteer equivalent
await page.locator(locator).fill('');
// Get the value of an attribute, for example, get the value of an input.
element(locator).getAttribute('value');
// Puppeteer equivalent
const element = await page.locator(locator).waitHandle();
const value = await element.getProperty('value');
```
### Example
Sample Protractor test:
```ts
describe('Protractor Demo', function () {
it('should add one and two', function () {
browser.get('http://juliemr.github.io/protractor-demo/');
element(by.model('first')).sendKeys(1);
element(by.model('second')).sendKeys(2);
element(by.id('gobutton')).click();
expect(element(by.binding('latest')).getText()).toEqual('3');
});
});
```
Sample Puppeteer migration:
```ts
import {setupBrowserHooks, getBrowserState} from './utils';
describe('Puppeteer Demo', function () {
setupBrowserHooks();
it('should add one and two', function () {
const {page} = getBrowserState();
await page.goto('http://juliemr.github.io/protractor-demo/');
await page.locator('.form-inline > input:nth-child(1)').fill('1');
await page.locator('.form-inline > input:nth-child(2)').fill('2');
await page.locator('#gobutton').fill('2');
const result = await page
.locator('.table tbody td:last-of-type')
.map(header => header.innerText)
.wait();
expect(result).toEqual('3');
});
});
```