mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
build: switch adev tests away from protractor
Reworks the tests in adev not to depend on Protractor.
(cherry picked from commit 7b74bee5b4)
This commit is contained in:
committed by
Jessica Janiuk
parent
3e02b0a2e5
commit
e120d2830b
@@ -1,15 +1,26 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Accessibility example e2e tests', () => {
|
||||
beforeEach(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display Accessibility Example', async () => {
|
||||
expect(await element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
||||
expect(await driver.findElement(webdriver.By.css('h1')).getText()).toEqual(
|
||||
'Accessibility Example',
|
||||
);
|
||||
});
|
||||
|
||||
it('should take a number and change progressbar width', async () => {
|
||||
await element(by.css('input')).sendKeys('16');
|
||||
expect(await element(by.css('input')).getAttribute('value')).toEqual('16');
|
||||
expect(await element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||
const input = driver.findElement(webdriver.By.css('input'));
|
||||
await input.sendKeys('16');
|
||||
expect(await input.getAttribute('value')).toEqual('16');
|
||||
expect(
|
||||
await driver
|
||||
.findElement(webdriver.By.css('app-example-progressbar div'))
|
||||
.getCssValue('width'),
|
||||
).toBe('48px');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import {AppPage} from './app.po';
|
||||
import {browser, logging} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
// Add your e2e tests here
|
||||
|
||||
afterEach(async () => {
|
||||
// Assert that there are no errors emitted from the browser
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
const logs = await driver.manage().logs().get(webdriver.logging.Type.BROWSER);
|
||||
expect(logs).not.toContain(
|
||||
jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry),
|
||||
level: webdriver.logging.Level.SEVERE,
|
||||
} as webdriver.logging.Entry),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,10 @@
|
||||
{
|
||||
"projectType": "cli",
|
||||
"overrideBoilerplate": [
|
||||
"tsconfig.json",
|
||||
"tsconfig.app.json"
|
||||
],
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--protractor-config=e2e/protractor-bazel.conf.js",
|
||||
"--no-webdriver-update",
|
||||
"--port=0"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
"projectType": "cli",
|
||||
"overrideBoilerplate": ["tsconfig.json", "tsconfig.app.json"],
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": ["e2e"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {browser} from 'protractor';
|
||||
import {logging} from 'selenium-webdriver';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import * as openClose from './open-close.po';
|
||||
import * as statusSlider from './status-slider.po';
|
||||
import * as toggle from './toggle.po';
|
||||
@@ -11,41 +10,32 @@ import {getLinkById, sleepFor} from './util';
|
||||
import {getComponentSection, getToggleButton} from './querying.po';
|
||||
|
||||
describe('Animation Tests', () => {
|
||||
let driver: webdriver.WebDriver;
|
||||
const routingAnimationDuration = 350;
|
||||
|
||||
const openCloseHref = getLinkById('open-close');
|
||||
const statusSliderHref = getLinkById('status');
|
||||
const toggleHref = getLinkById('toggle');
|
||||
const enterLeaveHref = getLinkById('enter-leave');
|
||||
const autoHref = getLinkById('auto');
|
||||
const filterHref = getLinkById('heroes');
|
||||
const heroGroupsHref = getLinkById('hero-groups');
|
||||
const queryingHref = getLinkById('querying');
|
||||
|
||||
const newPageSleepFor = (ms = 0) => sleepFor(ms + routingAnimationDuration);
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
describe('Open/Close Component', () => {
|
||||
const closedHeight = '100px';
|
||||
const openHeight = '200px';
|
||||
|
||||
beforeAll(async () => {
|
||||
await openCloseHref.click();
|
||||
await (await getLinkById(driver, 'open-close')).click();
|
||||
await newPageSleepFor(300);
|
||||
});
|
||||
|
||||
it('should be open', async () => {
|
||||
const toggleButton = openClose.getToggleButton();
|
||||
const container = openClose.getComponentContainer();
|
||||
const toggleButton = await openClose.getToggleButton(driver);
|
||||
const container = await openClose.getComponentContainer(driver);
|
||||
let text = await container.getText();
|
||||
|
||||
if (text.includes('Closed')) {
|
||||
await toggleButton.click();
|
||||
await browser.wait(
|
||||
async () => (await container.getCssValue('height')) === openHeight,
|
||||
2000,
|
||||
);
|
||||
await driver.wait(async () => (await container.getCssValue('height')) === openHeight, 2000);
|
||||
}
|
||||
|
||||
text = await container.getText();
|
||||
@@ -56,13 +46,13 @@ describe('Animation Tests', () => {
|
||||
});
|
||||
|
||||
it('should be closed', async () => {
|
||||
const toggleButton = openClose.getToggleButton();
|
||||
const container = openClose.getComponentContainer();
|
||||
const toggleButton = await openClose.getToggleButton(driver);
|
||||
const container = await openClose.getComponentContainer(driver);
|
||||
let text = await container.getText();
|
||||
|
||||
if (text.includes('Open')) {
|
||||
await toggleButton.click();
|
||||
await browser.wait(
|
||||
await driver.wait(
|
||||
async () => (await container.getCssValue('height')) === closedHeight,
|
||||
2000,
|
||||
);
|
||||
@@ -76,12 +66,12 @@ describe('Animation Tests', () => {
|
||||
});
|
||||
|
||||
it('should log animation events', async () => {
|
||||
const toggleButton = openClose.getToggleButton();
|
||||
const loggingCheckbox = openClose.getLoggingCheckbox();
|
||||
const toggleButton = await openClose.getToggleButton(driver);
|
||||
const loggingCheckbox = await openClose.getLoggingCheckbox(driver);
|
||||
await loggingCheckbox.click();
|
||||
await toggleButton.click();
|
||||
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
const logs = await driver.manage().logs().get(webdriver.logging.Type.BROWSER);
|
||||
const animationMessages = logs.filter(({message}) => message.includes('Animation'));
|
||||
|
||||
expect(animationMessages.length).toBeGreaterThan(0);
|
||||
@@ -93,18 +83,18 @@ describe('Animation Tests', () => {
|
||||
const inactiveColor = 'rgba(0, 0, 255, 1)';
|
||||
|
||||
beforeAll(async () => {
|
||||
await statusSliderHref.click();
|
||||
await (await getLinkById(driver, 'status')).click();
|
||||
await newPageSleepFor(2000);
|
||||
});
|
||||
|
||||
it('should be inactive with a blue background', async () => {
|
||||
const toggleButton = statusSlider.getToggleButton();
|
||||
const container = statusSlider.getComponentContainer();
|
||||
const toggleButton = await statusSlider.getToggleButton(driver);
|
||||
const container = await statusSlider.getComponentContainer(driver);
|
||||
let text = await container.getText();
|
||||
|
||||
if (text === 'Active') {
|
||||
await toggleButton.click();
|
||||
await browser.wait(
|
||||
await driver.wait(
|
||||
async () => (await container.getCssValue('backgroundColor')) === inactiveColor,
|
||||
3000,
|
||||
);
|
||||
@@ -118,13 +108,13 @@ describe('Animation Tests', () => {
|
||||
});
|
||||
|
||||
it('should be active with an orange background', async () => {
|
||||
const toggleButton = statusSlider.getToggleButton();
|
||||
const container = statusSlider.getComponentContainer();
|
||||
const toggleButton = await statusSlider.getToggleButton(driver);
|
||||
const container = await statusSlider.getComponentContainer(driver);
|
||||
let text = await container.getText();
|
||||
|
||||
if (text === 'Inactive') {
|
||||
await toggleButton.click();
|
||||
await browser.wait(
|
||||
await driver.wait(
|
||||
async () => (await container.getCssValue('backgroundColor')) === activeColor,
|
||||
3000,
|
||||
);
|
||||
@@ -140,16 +130,16 @@ describe('Animation Tests', () => {
|
||||
|
||||
describe('Toggle Animations Component', () => {
|
||||
beforeAll(async () => {
|
||||
await toggleHref.click();
|
||||
await (await getLinkById(driver, 'toggle')).click();
|
||||
await newPageSleepFor();
|
||||
});
|
||||
|
||||
it('should disabled animations on the child element', async () => {
|
||||
const toggleButton = toggle.getToggleAnimationsButton();
|
||||
const toggleButton = await toggle.getToggleAnimationsButton(driver);
|
||||
|
||||
await toggleButton.click();
|
||||
|
||||
const container = toggle.getComponentContainer();
|
||||
const container = await toggle.getComponentContainer(driver);
|
||||
const cssClasses = await container.getAttribute('class');
|
||||
|
||||
expect(cssClasses).toContain('ng-animate-disabled');
|
||||
@@ -158,13 +148,13 @@ describe('Animation Tests', () => {
|
||||
|
||||
describe('Enter/Leave Component', () => {
|
||||
beforeAll(async () => {
|
||||
await enterLeaveHref.click();
|
||||
await (await getLinkById(driver, 'enter-leave')).click();
|
||||
await newPageSleepFor(100);
|
||||
});
|
||||
|
||||
it('should attach a flyInOut trigger to the list of items', async () => {
|
||||
const heroesList = enterLeave.getHeroesList();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await enterLeave.getHeroesList(driver);
|
||||
const hero = heroesList[0];
|
||||
const cssClasses = await hero.getAttribute('class');
|
||||
const transform = await hero.getCssValue('transform');
|
||||
|
||||
@@ -173,75 +163,75 @@ describe('Animation Tests', () => {
|
||||
});
|
||||
|
||||
it('should remove the hero from the list when clicked', async () => {
|
||||
const heroesList = enterLeave.getHeroesList();
|
||||
const total = await heroesList.count();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await enterLeave.getHeroesList(driver);
|
||||
const total = heroesList.length;
|
||||
const hero = heroesList[0];
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
await driver.wait(async () => (await enterLeave.getHeroesList(driver)).length < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Auto Calculation Component', () => {
|
||||
beforeAll(async () => {
|
||||
await autoHref.click();
|
||||
await (await getLinkById(driver, 'auto')).click();
|
||||
await newPageSleepFor();
|
||||
});
|
||||
|
||||
it('should attach a shrinkOut trigger to the list of items', async () => {
|
||||
const heroesList = auto.getHeroesList();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await auto.getHeroesList(driver);
|
||||
const hero = heroesList[0];
|
||||
const cssClasses = await hero.getAttribute('class');
|
||||
|
||||
expect(cssClasses).toContain('ng-trigger-shrinkOut');
|
||||
});
|
||||
|
||||
it('should remove the hero from the list when clicked', async () => {
|
||||
const heroesList = auto.getHeroesList();
|
||||
const total = await heroesList.count();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await auto.getHeroesList(driver);
|
||||
const total = heroesList.length;
|
||||
const hero = heroesList[0];
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
await driver.wait(async () => (await auto.getHeroesList(driver)).length < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Filter/Stagger Component', () => {
|
||||
beforeAll(async () => {
|
||||
await filterHref.click();
|
||||
await (await getLinkById(driver, 'heroes')).click();
|
||||
await newPageSleepFor();
|
||||
});
|
||||
|
||||
it('should attach a filterAnimations trigger to the list container', async () => {
|
||||
const heroesList = filterStagger.getComponentContainer();
|
||||
const heroesList = await filterStagger.getComponentContainer(driver);
|
||||
const cssClasses = await heroesList.getAttribute('class');
|
||||
|
||||
expect(cssClasses).toContain('ng-trigger-filterAnimation');
|
||||
});
|
||||
|
||||
it('should filter down the list when a search is performed', async () => {
|
||||
const heroesList = filterStagger.getHeroesList();
|
||||
const total = await heroesList.count();
|
||||
const heroesList = await filterStagger.getHeroesList(driver);
|
||||
const total = heroesList.length;
|
||||
|
||||
const input = filterStagger.getInput();
|
||||
const input = await filterStagger.getInput(driver);
|
||||
await input.sendKeys('Mag');
|
||||
|
||||
await browser.wait(async () => (await heroesList.count()) === 2, 2000);
|
||||
await driver.wait(async () => (await filterStagger.getHeroesList(driver)).length === 2, 2000);
|
||||
|
||||
const newTotal = await heroesList.count();
|
||||
const newTotal = (await filterStagger.getHeroesList(driver)).length;
|
||||
expect(newTotal).toBeLessThan(total);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Hero Groups Component', () => {
|
||||
beforeAll(async () => {
|
||||
await heroGroupsHref.click();
|
||||
await (await getLinkById(driver, 'hero-groups')).click();
|
||||
await newPageSleepFor(400);
|
||||
});
|
||||
|
||||
it('should attach a flyInOut trigger to the list of items', async () => {
|
||||
const heroesList = heroGroups.getHeroesList();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await heroGroups.getHeroesList(driver);
|
||||
const hero = heroesList[0];
|
||||
const cssClasses = await hero.getAttribute('class');
|
||||
const transform = await hero.getCssValue('transform');
|
||||
const opacity = await hero.getCssValue('opacity');
|
||||
@@ -252,12 +242,12 @@ describe('Animation Tests', () => {
|
||||
});
|
||||
|
||||
it('should remove the hero from the list when clicked', async () => {
|
||||
const heroesList = heroGroups.getHeroesList();
|
||||
const total = await heroesList.count();
|
||||
const hero = heroesList.get(0);
|
||||
const heroesList = await heroGroups.getHeroesList(driver);
|
||||
const total = heroesList.length;
|
||||
const hero = heroesList[0];
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
await driver.wait(async () => (await heroGroups.getHeroesList(driver)).length < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -265,30 +255,32 @@ describe('Animation Tests', () => {
|
||||
const queryingAnimationDuration = 2500;
|
||||
|
||||
beforeAll(async () => {
|
||||
await queryingHref.click();
|
||||
await (await getLinkById(driver, 'querying')).click();
|
||||
await newPageSleepFor(queryingAnimationDuration);
|
||||
});
|
||||
|
||||
it('should toggle the section', async () => {
|
||||
const toggleButton = getToggleButton();
|
||||
const section = getComponentSection();
|
||||
const toggleButton = await getToggleButton(driver);
|
||||
const section = await getComponentSection(driver);
|
||||
|
||||
expect(await section.isPresent()).toBe(true);
|
||||
expect(await section.isDisplayed()).toBe(true);
|
||||
|
||||
// toggling off
|
||||
await toggleButton.click();
|
||||
await newPageSleepFor(queryingAnimationDuration);
|
||||
expect(await section.isPresent()).toBe(false);
|
||||
const sectionsOff = await driver.findElements(webdriver.By.css('app-querying section'));
|
||||
expect(sectionsOff.length).toBe(0);
|
||||
|
||||
// toggling on
|
||||
await toggleButton.click();
|
||||
await newPageSleepFor(queryingAnimationDuration);
|
||||
expect(await section.isPresent()).toBe(true);
|
||||
const sectionsOn = await driver.findElements(webdriver.By.css('app-querying section'));
|
||||
expect(sectionsOn.length).toBe(1);
|
||||
await newPageSleepFor(queryingAnimationDuration);
|
||||
});
|
||||
|
||||
it(`should disable the button for the animation's duration`, async () => {
|
||||
const toggleButton = getToggleButton();
|
||||
const toggleButton = await getToggleButton(driver);
|
||||
expect(await toggleButton.isEnabled()).toBe(true);
|
||||
|
||||
// toggling off
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-auto-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-auto-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-hero-list-auto');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-auto'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('ul');
|
||||
return locate(getComponent(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-hero-list-auto'), webdriver.By.css('ul'));
|
||||
}
|
||||
|
||||
export function getHeroesList() {
|
||||
return getComponentContainer().all(by.css('li'));
|
||||
export async function getHeroesList(driver: webdriver.WebDriver) {
|
||||
const container = await getComponentContainer(driver);
|
||||
return container.findElements(webdriver.By.css('li'));
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-enter-leave-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-enter-leave-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-hero-list-enter-leave');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-enter-leave'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('ul');
|
||||
return locate(getComponent(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-hero-list-enter-leave'), webdriver.By.css('ul'));
|
||||
}
|
||||
|
||||
export function getHeroesList() {
|
||||
return getComponentContainer().all(by.css('li'));
|
||||
export async function getHeroesList(driver: webdriver.WebDriver) {
|
||||
const container = await getComponentContainer(driver);
|
||||
return container.findElements(webdriver.By.css('li'));
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-page'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('ul');
|
||||
return locate(getPage(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-hero-list-page'), webdriver.By.css('ul'));
|
||||
}
|
||||
|
||||
export function getHeroesList() {
|
||||
return getComponentContainer().all(by.css('li'));
|
||||
export async function getHeroesList(driver: webdriver.WebDriver) {
|
||||
const container = await getComponentContainer(driver);
|
||||
return container.findElements(webdriver.By.css('li'));
|
||||
}
|
||||
|
||||
export function getInput() {
|
||||
const input = () => by.css('input');
|
||||
return locate(getPage(), input());
|
||||
export async function getInput(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-hero-list-page'), webdriver.By.css('input'));
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-groups-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-groups-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-hero-list-groups');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-hero-list-groups'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('ul');
|
||||
return locate(getComponent(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-hero-list-groups'), webdriver.By.css('ul'));
|
||||
}
|
||||
|
||||
export function getHeroesList() {
|
||||
return getComponentContainer().all(by.css('li'));
|
||||
export async function getHeroesList(driver: webdriver.WebDriver) {
|
||||
const container = await getComponentContainer(driver);
|
||||
return container.findElements(webdriver.By.css('li'));
|
||||
}
|
||||
|
||||
@@ -1,25 +1,27 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-open-close-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-open-close-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-open-close');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-open-close'));
|
||||
}
|
||||
|
||||
export function getToggleButton() {
|
||||
const toggleButton = () => by.buttonText('Toggle Open/Close');
|
||||
return locate(getComponent(), toggleButton());
|
||||
export async function getToggleButton(driver: webdriver.WebDriver) {
|
||||
const comp = await getComponent(driver);
|
||||
return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Open/Close"]'));
|
||||
}
|
||||
|
||||
export function getLoggingCheckbox() {
|
||||
const loggingCheckbox = () => by.css('section > input[type="checkbox"]');
|
||||
return locate(getPage(), loggingCheckbox());
|
||||
export async function getLoggingCheckbox(driver: webdriver.WebDriver) {
|
||||
return locate(
|
||||
driver,
|
||||
webdriver.By.css('app-open-close-page'),
|
||||
webdriver.By.css('section > input[type="checkbox"]'),
|
||||
);
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('div');
|
||||
return locate(getComponent(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-open-close'), webdriver.By.css('div'));
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-querying');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-querying'));
|
||||
}
|
||||
|
||||
export function getToggleButton() {
|
||||
const toggleButton = () => by.className('toggle');
|
||||
return locate(getComponent(), toggleButton());
|
||||
export async function getToggleButton(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-querying'), webdriver.By.className('toggle'));
|
||||
}
|
||||
|
||||
export function getComponentSection() {
|
||||
const findSection = () => by.css('section');
|
||||
return locate(getComponent(), findSection());
|
||||
export async function getComponentSection(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-querying'), webdriver.By.css('section'));
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-status-slider-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-status-slider-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-status-slider');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-status-slider'));
|
||||
}
|
||||
|
||||
export function getToggleButton() {
|
||||
const toggleButton = () => by.buttonText('Toggle Status');
|
||||
return locate(getComponent(), toggleButton());
|
||||
export async function getToggleButton(driver: webdriver.WebDriver) {
|
||||
const comp = await getComponent(driver);
|
||||
return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Status"]'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('div');
|
||||
return locate(getComponent(), findContainer());
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
return locate(driver, webdriver.By.css('app-status-slider'), webdriver.By.css('div'));
|
||||
}
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
import {by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-toggle-animations-child-page');
|
||||
export function getPage(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-toggle-animations-child-page'));
|
||||
}
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-open-close-toggle');
|
||||
export function getComponent(driver: webdriver.WebDriver) {
|
||||
return driver.findElement(webdriver.By.css('app-open-close-toggle'));
|
||||
}
|
||||
|
||||
export function getToggleButton() {
|
||||
const toggleButton = () => by.buttonText('Toggle Open/Closed');
|
||||
return locate(getComponent(), toggleButton());
|
||||
export async function getToggleButton(driver: webdriver.WebDriver) {
|
||||
const comp = await getComponent(driver);
|
||||
return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Open/Closed"]'));
|
||||
}
|
||||
|
||||
export function getToggleAnimationsButton() {
|
||||
const toggleAnimationsButton = () => by.buttonText('Toggle Animations');
|
||||
return locate(getComponent(), toggleAnimationsButton());
|
||||
export async function getToggleAnimationsButton(driver: webdriver.WebDriver) {
|
||||
const comp = await getComponent(driver);
|
||||
return comp.findElement(webdriver.By.xpath('.//button[normalize-space()="Toggle Animations"]'));
|
||||
}
|
||||
|
||||
export function getComponentContainer() {
|
||||
const findContainer = () => by.css('div');
|
||||
return locate(getComponent()).all(findContainer()).get(0);
|
||||
export async function getComponentContainer(driver: webdriver.WebDriver) {
|
||||
const comp = await getComponent(driver);
|
||||
const divs = await comp.findElements(webdriver.By.css('div'));
|
||||
return divs[0];
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import {Locator, ElementFinder, browser, by, element} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
/**
|
||||
*
|
||||
* locate(finder1, finder2) => element(finder1).element(finder2).element(finderN);
|
||||
* locate(parent, finder1, finder2) => parent.findElement(finder1).findElement(finder2);
|
||||
*/
|
||||
export function locate(locator: Locator, ...locators: Locator[]) {
|
||||
return locators.reduce(
|
||||
(current: ElementFinder, next: Locator) => current.element(next),
|
||||
element(locator),
|
||||
) as ElementFinder;
|
||||
export async function locate(
|
||||
parent: webdriver.WebDriver | webdriver.WebElement,
|
||||
...locators: webdriver.Locator[]
|
||||
): Promise<webdriver.WebElement> {
|
||||
let current: webdriver.WebElement = await parent.findElement(locators[0]);
|
||||
for (let i = 1; i < locators.length; i++) {
|
||||
current = await current.findElement(locators[i]);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
export async function sleepFor(time = 1000) {
|
||||
return await browser.sleep(time);
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
|
||||
export function getLinkById(id: string) {
|
||||
return element(by.css(`a[id=${id}]`));
|
||||
export function getLinkById(driver: webdriver.WebDriver, id: string) {
|
||||
return driver.findElement(webdriver.By.css(`a[id=${id}]`));
|
||||
}
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import {ApplicationConfig} from '@angular/core';
|
||||
import {routes} from './app.routes';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {provideAnimations} from '@angular/platform-browser/animations';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// needed for supporting e2e tests
|
||||
provideProtractorTestingSupport(),
|
||||
provideRouter(routes),
|
||||
provideAnimations(),
|
||||
],
|
||||
providers: [provideRouter(routes), provideAnimations()],
|
||||
};
|
||||
|
||||
@@ -1,27 +1,37 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Attribute directives', () => {
|
||||
let driver: webdriver.WebDriver;
|
||||
const title = 'My First Attribute Directive';
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it(`should display correct title: ${title}`, async () => {
|
||||
expect(await element(by.css('h1')).getText()).toEqual(title);
|
||||
expect(await driver.findElement(webdriver.By.css('h1')).getText()).toEqual(title);
|
||||
});
|
||||
|
||||
it('should be able to select green highlight', async () => {
|
||||
const highlightedEle = element(by.cssContainingText('p', 'Highlight me!'));
|
||||
const paragraphs = await driver.findElements(webdriver.By.css('p'));
|
||||
let highlightedEle: webdriver.WebElement | null = null;
|
||||
for (const p of paragraphs) {
|
||||
if ((await p.getText()).includes('Highlight me!')) {
|
||||
highlightedEle = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const lightGreen = 'rgba(144, 238, 144, 1)';
|
||||
const getBgColor = () => highlightedEle.getCssValue('background-color');
|
||||
const getBgColor = () => highlightedEle!.getCssValue('background-color');
|
||||
|
||||
expect(await highlightedEle.getCssValue('background-color')).not.toEqual(lightGreen);
|
||||
expect(await getBgColor()).not.toEqual(lightGreen);
|
||||
|
||||
const greenRb = element.all(by.css('input')).get(0);
|
||||
const greenRb = (await driver.findElements(webdriver.By.css('input')))[0];
|
||||
await greenRb.click();
|
||||
await browser.actions().mouseMove(highlightedEle).perform();
|
||||
await driver.actions().move({origin: highlightedEle!}).perform();
|
||||
|
||||
// Wait for up to 4s for the background color to be updated,
|
||||
// to account for slow environments (e.g. CI).
|
||||
await browser.wait(async () => (await getBgColor()) === lightGreen, 4000);
|
||||
await driver.wait(async () => (await getBgColor()) === lightGreen, 4000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// #docregion
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Built-in Directives', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should have title Built-in Directives', async () => {
|
||||
const title = element.all(by.css('h1')).get(0);
|
||||
const title = (await driver.findElements(webdriver.By.css('h1')))[0];
|
||||
expect(await title.getText()).toEqual('Built-in Directives');
|
||||
});
|
||||
|
||||
it('should change first Teapot header', async () => {
|
||||
const firstLabel = element.all(by.css('p')).get(0);
|
||||
const firstInput = element.all(by.css('input')).get(0);
|
||||
const firstLabel = (await driver.findElements(webdriver.By.css('p')))[0];
|
||||
const firstInput = (await driver.findElements(webdriver.By.css('input')))[0];
|
||||
|
||||
expect(await firstLabel.getText()).toEqual('Current item name: Teapot');
|
||||
await firstInput.sendKeys('abc');
|
||||
@@ -18,48 +22,60 @@ describe('Built-in Directives', () => {
|
||||
});
|
||||
|
||||
it('should modify sentence when modified checkbox checked', async () => {
|
||||
const modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
||||
const modifiedSentence = element.all(by.css('div')).get(1);
|
||||
const modifiedChkbxLabel = (
|
||||
await driver.findElements(webdriver.By.css('input[type="checkbox"]'))
|
||||
)[1];
|
||||
const modifiedSentence = (await driver.findElements(webdriver.By.css('div')))[1];
|
||||
|
||||
await modifiedChkbxLabel.click();
|
||||
expect(await modifiedSentence.getText()).toContain('modified');
|
||||
});
|
||||
|
||||
it('should modify sentence when normal checkbox checked', async () => {
|
||||
const normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
|
||||
const normalSentence = element.all(by.css('div')).get(7);
|
||||
const normalChkbxLabel = (
|
||||
await driver.findElements(webdriver.By.css('input[type="checkbox"]'))
|
||||
)[4];
|
||||
const normalSentence = (await driver.findElements(webdriver.By.css('div')))[7];
|
||||
|
||||
await normalChkbxLabel.click();
|
||||
expect(await normalSentence.getText()).toContain('normal weight and, extra large');
|
||||
});
|
||||
|
||||
it('should toggle app-item-detail', async () => {
|
||||
const toggleButton = element.all(by.css('button')).get(3);
|
||||
const toggledDiv = element.all(by.css('app-item-detail')).get(0);
|
||||
const toggleButton = (await driver.findElements(webdriver.By.css('button')))[3];
|
||||
const toggledDiv = (await driver.findElements(webdriver.By.css('app-item-detail')))[0];
|
||||
|
||||
await toggleButton.click();
|
||||
expect(await toggledDiv.isDisplayed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should hide app-item-detail', async () => {
|
||||
const hiddenMessage = element.all(by.css('p')).get(10);
|
||||
const hiddenDiv = element.all(by.css('app-item-detail')).get(2);
|
||||
const hiddenMessage = (await driver.findElements(webdriver.By.css('p')))[10];
|
||||
const hiddenDiv = (await driver.findElements(webdriver.By.css('app-item-detail')))[2];
|
||||
|
||||
expect(await hiddenMessage.getText()).toContain('in the DOM');
|
||||
expect(await hiddenDiv.isDisplayed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should have 10 lists each containing the string Teapot', async () => {
|
||||
const listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
|
||||
expect(await listDiv.count()).toBe(10);
|
||||
const boxes = await driver.findElements(webdriver.By.css('.box'));
|
||||
const teapotBoxes: webdriver.WebElement[] = [];
|
||||
for (const b of boxes) {
|
||||
if ((await b.getText()).includes('Teapot')) {
|
||||
teapotBoxes.push(b);
|
||||
}
|
||||
}
|
||||
expect(teapotBoxes.length).toBe(10);
|
||||
});
|
||||
|
||||
it('should switch case', async () => {
|
||||
const tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
|
||||
const tvDiv = element(by.css('app-lost-item'));
|
||||
const tvRadioButton = (await driver.findElements(webdriver.By.css('input[type="radio"]')))[3];
|
||||
const tvDiv = driver.findElement(webdriver.By.css('app-lost-item'));
|
||||
|
||||
const fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
|
||||
const fishbowlDiv = element(by.css('app-unknown-item'));
|
||||
const fishbowlRadioButton = (
|
||||
await driver.findElements(webdriver.By.css('input[type="radio"]'))
|
||||
)[4];
|
||||
const fishbowlDiv = driver.findElement(webdriver.By.css('app-unknown-item'));
|
||||
|
||||
await tvRadioButton.click();
|
||||
expect(await tvDiv.getText()).toContain('Television');
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,21 +1,34 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Dynamic Form', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should submit form', async () => {
|
||||
const firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
|
||||
const firstNameElement = (
|
||||
await driver.findElements(webdriver.By.css('input[id=firstName]'))
|
||||
)[0];
|
||||
expect(await firstNameElement.getAttribute('value')).toEqual('Bombasto');
|
||||
|
||||
const emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
|
||||
const emailElement = (await driver.findElements(webdriver.By.css('input[id=emailAddress]')))[0];
|
||||
const email = 'test@test.com';
|
||||
await emailElement.sendKeys(email);
|
||||
expect(await emailElement.getAttribute('value')).toEqual(email);
|
||||
|
||||
await element(by.css('select option[value="solid"]')).click();
|
||||
await element.all(by.css('button')).get(0).click();
|
||||
expect(
|
||||
await element(by.cssContainingText('strong', 'Saved the following values')).isPresent(),
|
||||
).toBe(true);
|
||||
await (await driver.findElement(webdriver.By.css('select option[value="solid"]'))).click();
|
||||
await (await driver.findElements(webdriver.By.css('button')))[0].click();
|
||||
|
||||
const strongs = await driver.findElements(webdriver.By.css('strong'));
|
||||
let found = false;
|
||||
for (const s of strongs) {
|
||||
if ((await s.getText()).includes('Saved the following values')) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(found).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// #docregion
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
});
|
||||
bootstrapApplication(AppComponent);
|
||||
|
||||
@@ -1,81 +1,97 @@
|
||||
import {browser, by, element, ElementFinder, ExpectedConditions as EC} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Elements', () => {
|
||||
const messageInput = element(by.css('input'));
|
||||
const popupButtons = element.all(by.css('button'));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
// Helpers
|
||||
const click = async (elem: ElementFinder) => {
|
||||
// Waiting for the element to be clickable, makes the tests less flaky.
|
||||
await browser.wait(EC.elementToBeClickable(elem), 5000);
|
||||
const click = async (elem: webdriver.WebElement) => {
|
||||
await driver.wait(webdriver.until.elementIsVisible(elem), 5000);
|
||||
await elem.click();
|
||||
};
|
||||
const waitForText = async (elem: ElementFinder) => {
|
||||
// Waiting for the element to have some text, makes the tests less flaky.
|
||||
await browser.wait(async () => /\S/.test(await elem.getText()), 5000);
|
||||
|
||||
const waitForText = async (elem: webdriver.WebElement) => {
|
||||
await driver.wait(async () => /\S/.test(await elem.getText()), 5000);
|
||||
};
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
const isPresent = async (locator: webdriver.Locator) => {
|
||||
const els = await driver.findElements(locator);
|
||||
return els.length > 0;
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
describe('popup component', () => {
|
||||
const popupComponentButton = popupButtons.get(0);
|
||||
const popupComponent = element(by.css('popup-component'));
|
||||
const closeButton = popupComponent.element(by.css('button'));
|
||||
|
||||
it('should be displayed on button click', async () => {
|
||||
expect(await popupComponent.isPresent()).toBe(false);
|
||||
const popupComponentLocator = webdriver.By.css('popup-component');
|
||||
expect(await isPresent(popupComponentLocator)).toBe(false);
|
||||
|
||||
await click(popupComponentButton);
|
||||
expect(await popupComponent.isPresent()).toBe(true);
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[0]);
|
||||
expect(await isPresent(popupComponentLocator)).toBe(true);
|
||||
});
|
||||
|
||||
it('should display the specified message', async () => {
|
||||
const messageInput = await driver.findElement(webdriver.By.css('input'));
|
||||
await messageInput.clear();
|
||||
await messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
await click(popupComponentButton);
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[0]);
|
||||
|
||||
const popupComponent = await driver.findElement(webdriver.By.css('popup-component'));
|
||||
await waitForText(popupComponent);
|
||||
|
||||
expect(await popupComponent.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
it('should be closed on "close" button click', async () => {
|
||||
await click(popupComponentButton);
|
||||
expect(await popupComponent.isPresent()).toBe(true);
|
||||
const popupComponentLocator = webdriver.By.css('popup-component');
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[0]);
|
||||
expect(await isPresent(popupComponentLocator)).toBe(true);
|
||||
|
||||
const popupComponent = await driver.findElement(popupComponentLocator);
|
||||
const closeButton = await popupComponent.findElement(webdriver.By.css('button'));
|
||||
await click(closeButton);
|
||||
expect(await popupComponent.isPresent()).toBe(false);
|
||||
expect(await isPresent(popupComponentLocator)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('popup element', () => {
|
||||
const popupElementButton = popupButtons.get(1);
|
||||
const popupElement = element(by.css('popup-element'));
|
||||
const closeButton = popupElement.element(by.css('button'));
|
||||
|
||||
it('should be displayed on button click', async () => {
|
||||
expect(await popupElement.isPresent()).toBe(false);
|
||||
const popupElementLocator = webdriver.By.css('popup-element');
|
||||
expect(await isPresent(popupElementLocator)).toBe(false);
|
||||
|
||||
await click(popupElementButton);
|
||||
expect(await popupElement.isPresent()).toBe(true);
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[1]);
|
||||
expect(await isPresent(popupElementLocator)).toBe(true);
|
||||
});
|
||||
|
||||
it('should display the specified message', async () => {
|
||||
const messageInput = await driver.findElement(webdriver.By.css('input'));
|
||||
await messageInput.clear();
|
||||
await messageInput.sendKeys('Angular rocks!');
|
||||
|
||||
await click(popupElementButton);
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[1]);
|
||||
|
||||
const popupElement = await driver.findElement(webdriver.By.css('popup-element'));
|
||||
await waitForText(popupElement);
|
||||
|
||||
expect(await popupElement.getText()).toContain('Popup: Angular rocks!');
|
||||
});
|
||||
|
||||
it('should be closed on "close" button click', async () => {
|
||||
await click(popupElementButton);
|
||||
expect(await popupElement.isPresent()).toBe(true);
|
||||
const popupElementLocator = webdriver.By.css('popup-element');
|
||||
const popupButtons = await driver.findElements(webdriver.By.css('button'));
|
||||
await click(popupButtons[1]);
|
||||
expect(await isPresent(popupElementLocator)).toBe(true);
|
||||
|
||||
const popupElement = await driver.findElement(popupElementLocator);
|
||||
const closeButton = await popupElement.findElement(webdriver.By.css('button'));
|
||||
await click(closeButton);
|
||||
expect(await popupElement.isPresent()).toBe(false);
|
||||
expect(await isPresent(popupElementLocator)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import {browser, element, by, protractor, ElementFinder, ElementArrayFinder} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
// THESE TESTS ARE INCOMPLETE
|
||||
describe('Form Validation Tests', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
describe('Template-driven form', () => {
|
||||
beforeAll(() => {
|
||||
@@ -25,222 +29,221 @@ describe('Form Validation Tests', () => {
|
||||
asyncValidationTests();
|
||||
crossValidationTests();
|
||||
});
|
||||
});
|
||||
|
||||
//////////
|
||||
const testName = 'Test Name';
|
||||
|
||||
const testName = 'Test Name';
|
||||
|
||||
let page: {
|
||||
section: ElementFinder;
|
||||
form: ElementFinder;
|
||||
title: ElementFinder;
|
||||
nameInput: ElementFinder;
|
||||
roleInput: ElementFinder;
|
||||
skillSelect: ElementFinder;
|
||||
skillOption: ElementFinder;
|
||||
errorMessages: ElementArrayFinder;
|
||||
actorFormButtons: ElementArrayFinder;
|
||||
actorSubmitted: ElementFinder;
|
||||
roleErrors: ElementFinder;
|
||||
crossValidationErrorMessage: ElementFinder;
|
||||
};
|
||||
|
||||
function getPage(sectionTag: string) {
|
||||
const section = element(by.css(sectionTag));
|
||||
const buttons = section.all(by.css('button'));
|
||||
|
||||
page = {
|
||||
section,
|
||||
form: section.element(by.css('form')),
|
||||
title: section.element(by.css('h2')),
|
||||
nameInput: section.element(by.css('#name')),
|
||||
roleInput: section.element(by.css('#role')),
|
||||
skillSelect: section.element(by.css('#skill')),
|
||||
skillOption: section.element(by.css('#skill option')),
|
||||
errorMessages: section.all(by.css('div.alert')),
|
||||
actorFormButtons: buttons,
|
||||
actorSubmitted: section.element(by.css('.submitted-message')),
|
||||
roleErrors: section.element(by.css('.role-errors')),
|
||||
crossValidationErrorMessage: section.element(by.css('.cross-validation-error-message')),
|
||||
let page: {
|
||||
sectionTag: string;
|
||||
section: () => webdriver.WebElement;
|
||||
form: () => webdriver.WebElement;
|
||||
title: () => webdriver.WebElement;
|
||||
nameInput: () => webdriver.WebElement;
|
||||
roleInput: () => webdriver.WebElement;
|
||||
skillSelect: () => webdriver.WebElement;
|
||||
skillOption: () => webdriver.WebElement;
|
||||
errorMessages: () => Promise<webdriver.WebElement[]>;
|
||||
actorFormButtons: () => Promise<webdriver.WebElement[]>;
|
||||
actorSubmitted: () => webdriver.WebElement;
|
||||
roleErrors: () => webdriver.WebElement;
|
||||
crossValidationErrorMessage: () => webdriver.WebElement;
|
||||
};
|
||||
}
|
||||
|
||||
function tests(title: string) {
|
||||
it('should display correct title', async () => {
|
||||
expect(await page.title.getText()).toContain(title);
|
||||
});
|
||||
function getPage(sectionTag: string) {
|
||||
const sec = () => driver.findElement(webdriver.By.css(sectionTag));
|
||||
|
||||
it('should not display submitted message before submit', async () => {
|
||||
expect(await page.actorSubmitted.isElementPresent(by.css('p'))).toBe(false);
|
||||
});
|
||||
page = {
|
||||
sectionTag,
|
||||
section: sec,
|
||||
form: () => sec().findElement(webdriver.By.css('form')),
|
||||
title: () => sec().findElement(webdriver.By.css('h2')),
|
||||
nameInput: () => sec().findElement(webdriver.By.css('#name')),
|
||||
roleInput: () => sec().findElement(webdriver.By.css('#role')),
|
||||
skillSelect: () => sec().findElement(webdriver.By.css('#skill')),
|
||||
skillOption: () => sec().findElement(webdriver.By.css('#skill option')),
|
||||
errorMessages: () => sec().findElements(webdriver.By.css('div.alert')),
|
||||
actorFormButtons: () => sec().findElements(webdriver.By.css('button')),
|
||||
actorSubmitted: () => sec().findElement(webdriver.By.css('.submitted-message')),
|
||||
roleErrors: () => sec().findElement(webdriver.By.css('.role-errors')),
|
||||
crossValidationErrorMessage: () =>
|
||||
sec().findElement(webdriver.By.css('.cross-validation-error-message')),
|
||||
};
|
||||
}
|
||||
|
||||
it('should have form buttons', async () => {
|
||||
expect(await page.actorFormButtons.count()).toEqual(2);
|
||||
});
|
||||
function tests(title: string) {
|
||||
it('should display correct title', async () => {
|
||||
expect(await page.title().getText()).toContain(title);
|
||||
});
|
||||
|
||||
it('should have error at start', async () => {
|
||||
await expectFormIsInvalid();
|
||||
});
|
||||
it('should not display submitted message before submit', async () => {
|
||||
const p = await page.actorSubmitted().findElements(webdriver.By.css('p'));
|
||||
expect(p.length).toBe(0);
|
||||
});
|
||||
|
||||
// it('showForm', () => {
|
||||
// page.form.getInnerHtml().then(html => console.log(html));
|
||||
// });
|
||||
it('should have form buttons', async () => {
|
||||
expect((await page.actorFormButtons()).length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should have disabled submit button', async () => {
|
||||
expect(await page.actorFormButtons.get(0).isEnabled()).toBe(false);
|
||||
});
|
||||
it('should have error at start', async () => {
|
||||
await expectFormIsInvalid();
|
||||
});
|
||||
|
||||
it('resetting name to valid name should clear errors', async () => {
|
||||
const ele = page.nameInput;
|
||||
expect(await ele.isPresent()).toBe(true, 'nameInput should exist');
|
||||
await ele.clear();
|
||||
await ele.sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
it('should have disabled submit button', async () => {
|
||||
expect(await (await page.actorFormButtons())[0].isEnabled()).toBe(false);
|
||||
});
|
||||
|
||||
it('should produce "required" error after clearing name', async () => {
|
||||
await page.nameInput.clear();
|
||||
// await page.roleInput.click(); // to blur ... didn't work
|
||||
await page.nameInput.sendKeys('x', protractor.Key.BACK_SPACE); // ugh!
|
||||
expect(await page.form.getAttribute('class')).toMatch('ng-invalid');
|
||||
expect(await page.errorMessages.get(0).getText()).toContain('required');
|
||||
});
|
||||
it('resetting name to valid name should clear errors', async () => {
|
||||
const ele = page.nameInput();
|
||||
expect(await ele.isDisplayed()).toBe(true, 'nameInput should exist');
|
||||
await ele.clear();
|
||||
await ele.sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
|
||||
it('should produce "at least 4 characters" error when name="x"', async () => {
|
||||
await page.nameInput.clear();
|
||||
await page.nameInput.sendKeys('x'); // too short
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.errorMessages.get(0).getText()).toContain('at least 4 characters');
|
||||
});
|
||||
it('should produce "required" error after clearing name', async () => {
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys('x', webdriver.Key.BACK_SPACE);
|
||||
expect(await page.form().getAttribute('class')).toMatch('ng-invalid');
|
||||
expect(await (await page.errorMessages())[0].getText()).toContain('required');
|
||||
});
|
||||
|
||||
it('resetting name to valid name again should clear errors', async () => {
|
||||
await page.nameInput.sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
it('should produce "at least 4 characters" error when name="x"', async () => {
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys('x');
|
||||
await expectFormIsInvalid();
|
||||
expect(await (await page.errorMessages())[0].getText()).toContain('at least 4 characters');
|
||||
});
|
||||
|
||||
it('should have enabled submit button', async () => {
|
||||
const submitBtn = page.actorFormButtons.get(0);
|
||||
expect(await submitBtn.isEnabled()).toBe(true);
|
||||
});
|
||||
it('resetting name to valid name again should clear errors', async () => {
|
||||
await page.nameInput().sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
|
||||
it('should hide form after submit', async () => {
|
||||
await page.actorFormButtons.get(0).click();
|
||||
expect(await page.actorFormButtons.get(0).isDisplayed()).toBe(false);
|
||||
});
|
||||
it('should have enabled submit button', async () => {
|
||||
const submitBtn = (await page.actorFormButtons())[0];
|
||||
expect(await submitBtn.isEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
it('submitted form should be displayed', async () => {
|
||||
expect(await page.actorSubmitted.isElementPresent(by.css('p'))).toBe(true);
|
||||
});
|
||||
it('should hide form after submit', async () => {
|
||||
await (await page.actorFormButtons())[0].click();
|
||||
const forms = await driver.findElements(webdriver.By.css(`${page.sectionTag} form`));
|
||||
expect(forms.length === 0 || !(await forms[0].isDisplayed())).toBe(true);
|
||||
});
|
||||
|
||||
it('submitted form should have new actor name', async () => {
|
||||
expect(await page.actorSubmitted.getText()).toContain(testName);
|
||||
});
|
||||
it('submitted form should be displayed', async () => {
|
||||
const p = await page.actorSubmitted().findElements(webdriver.By.css('p'));
|
||||
expect(p.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('clicking edit button should reveal form again', async () => {
|
||||
const newFormBtn = page.actorSubmitted.element(by.css('button'));
|
||||
await newFormBtn.click();
|
||||
expect(await page.actorSubmitted.isElementPresent(by.css('p'))).toBe(
|
||||
false,
|
||||
'submitted hidden again',
|
||||
);
|
||||
expect(await page.title.isDisplayed()).toBe(true, 'can see form title');
|
||||
});
|
||||
}
|
||||
it('submitted form should have new actor name', async () => {
|
||||
expect(await page.actorSubmitted().getText()).toContain(testName);
|
||||
});
|
||||
|
||||
async function expectFormIsValid() {
|
||||
expect(await page.form.getAttribute('class')).toMatch('ng-valid');
|
||||
}
|
||||
it('clicking edit button should reveal form again', async () => {
|
||||
const newFormBtn = page.actorSubmitted().findElement(webdriver.By.css('button'));
|
||||
await newFormBtn.click();
|
||||
const p = await page.actorSubmitted().findElements(webdriver.By.css('p'));
|
||||
expect(p.length).toBe(0, 'submitted hidden again');
|
||||
expect(await page.title().isDisplayed()).toBe(true, 'can see form title');
|
||||
});
|
||||
}
|
||||
|
||||
async function expectFormIsInvalid() {
|
||||
expect(await page.form.getAttribute('class')).toMatch('ng-invalid');
|
||||
}
|
||||
async function expectFormIsValid() {
|
||||
expect(await page.form().getAttribute('class')).toMatch('ng-valid');
|
||||
}
|
||||
|
||||
async function triggerRoleValidation() {
|
||||
// role has updateOn set to 'blur', click outside of the input to trigger the blur event
|
||||
await element(by.css('app-root')).click();
|
||||
}
|
||||
async function expectFormIsInvalid() {
|
||||
expect(await page.form().getAttribute('class')).toMatch('ng-invalid');
|
||||
}
|
||||
|
||||
async function waitForAlterEgoValidation() {
|
||||
// role async validation will be performed in 400ms
|
||||
await browser.sleep(400);
|
||||
}
|
||||
async function triggerRoleValidation() {
|
||||
await driver.findElement(webdriver.By.css('app-root')).click();
|
||||
}
|
||||
|
||||
function bobTests() {
|
||||
const emsg = 'Name cannot be Bob.';
|
||||
async function waitForAlterEgoValidation() {
|
||||
await new Promise((resolve) => setTimeout(resolve, 400));
|
||||
}
|
||||
|
||||
it('should produce "no bob" error after setting name to "Bobby"', async () => {
|
||||
// Re-populate select element
|
||||
await page.skillSelect.click();
|
||||
await page.skillOption.click();
|
||||
function bobTests() {
|
||||
const emsg = 'Name cannot be Bob.';
|
||||
|
||||
await page.nameInput.clear();
|
||||
await page.nameInput.sendKeys('Bobby');
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.errorMessages.get(0).getText()).toBe(emsg);
|
||||
});
|
||||
it('should produce "no bob" error after setting name to "Bobby"', async () => {
|
||||
await page.skillSelect().click();
|
||||
await page.skillOption().click();
|
||||
|
||||
it('should be ok again with valid name', async () => {
|
||||
await page.nameInput.clear();
|
||||
await page.nameInput.sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
}
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys('Bobby');
|
||||
await expectFormIsInvalid();
|
||||
expect(await (await page.errorMessages())[0].getText()).toBe(emsg);
|
||||
});
|
||||
|
||||
function asyncValidationTests() {
|
||||
const emsg = 'Role is already taken.';
|
||||
it('should be ok again with valid name', async () => {
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys(testName);
|
||||
await expectFormIsValid();
|
||||
});
|
||||
}
|
||||
|
||||
it(`should produce "${emsg}" error after setting role to Eric`, async () => {
|
||||
await page.roleInput.clear();
|
||||
await page.roleInput.sendKeys('Eric');
|
||||
function asyncValidationTests() {
|
||||
const emsg = 'Role is already taken.';
|
||||
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
it(`should produce "${emsg}" error after setting role to Eric`, async () => {
|
||||
await page.roleInput().clear();
|
||||
await page.roleInput().sendKeys('Eric');
|
||||
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.roleErrors.getText()).toBe(emsg);
|
||||
});
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
|
||||
it('should be ok again with different values', async () => {
|
||||
await page.roleInput.clear();
|
||||
await page.roleInput.sendKeys('John');
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.roleErrors().getText()).toBe(emsg);
|
||||
});
|
||||
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
it('should be ok again with different values', async () => {
|
||||
await page.roleInput().clear();
|
||||
await page.roleInput().sendKeys('John');
|
||||
|
||||
await expectFormIsValid();
|
||||
expect(await page.roleErrors.isPresent()).toBe(false);
|
||||
});
|
||||
}
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
|
||||
function crossValidationTests() {
|
||||
const emsg = 'Name cannot match role.';
|
||||
await expectFormIsValid();
|
||||
const roleErrors = await driver.findElements(
|
||||
webdriver.By.css(`${page.sectionTag} .role-errors`),
|
||||
);
|
||||
expect(roleErrors.length).toBe(0);
|
||||
});
|
||||
}
|
||||
|
||||
it(`should produce "${emsg}" error after setting name and role to the same value`, async () => {
|
||||
await page.nameInput.clear();
|
||||
await page.nameInput.sendKeys('Romeo');
|
||||
function crossValidationTests() {
|
||||
const emsg = 'Name cannot match role.';
|
||||
|
||||
await page.roleInput.clear();
|
||||
await page.roleInput.sendKeys('Romeo');
|
||||
it(`should produce "${emsg}" error after setting name and role to the same value`, async () => {
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys('Romeo');
|
||||
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
await page.roleInput().clear();
|
||||
await page.roleInput().sendKeys('Romeo');
|
||||
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.crossValidationErrorMessage.getText()).toBe(emsg);
|
||||
});
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
|
||||
it('should be ok again with different values', async () => {
|
||||
await page.nameInput.clear();
|
||||
await page.nameInput.sendKeys('Romeo');
|
||||
await expectFormIsInvalid();
|
||||
expect(await page.crossValidationErrorMessage().getText()).toBe(emsg);
|
||||
});
|
||||
|
||||
await page.roleInput.clear();
|
||||
await page.roleInput.sendKeys('Juliet');
|
||||
it('should be ok again with different values', async () => {
|
||||
await page.nameInput().clear();
|
||||
await page.nameInput().sendKeys('Romeo');
|
||||
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
await page.roleInput().clear();
|
||||
await page.roleInput().sendKeys('Juliet');
|
||||
|
||||
await expectFormIsValid();
|
||||
expect(await page.crossValidationErrorMessage.isPresent()).toBe(false);
|
||||
});
|
||||
}
|
||||
await triggerRoleValidation();
|
||||
await waitForAlterEgoValidation();
|
||||
|
||||
await expectFormIsValid();
|
||||
const crossErrors = await driver.findElements(
|
||||
webdriver.By.css(`${page.sectionTag} .cross-validation-error-message`),
|
||||
);
|
||||
expect(crossErrors.length).toBe(0);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import {AppPage} from './app.po';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('forms-overview App', () => {
|
||||
let page: AppPage;
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display a title', async () => {
|
||||
await page.navigateTo();
|
||||
expect(await page.getTitleText()).toEqual('Forms Overview');
|
||||
expect(await driver.findElement(webdriver.By.css('h1, h2')).getText()).toEqual(
|
||||
'Forms Overview',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"tests": [
|
||||
{"cmd": "yarn", "args": ["test", "--browsers=ChromeHeadlessNoSandbox", "--no-watch"]},
|
||||
{"cmd": "yarn", "args": ["e2e", "--configuration=production", "--protractor-config=e2e/protractor-bazel.conf.js", "--no-webdriver-update", "--port=0"]}
|
||||
{"cmd": "yarn", "args": ["e2e", "--configuration=production"]}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,43 +1,52 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Forms Tests', () => {
|
||||
beforeEach(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display correct title', async () => {
|
||||
expect(await element.all(by.css('h1')).get(0).getText()).toEqual('Actor Form');
|
||||
const h1s = await driver.findElements(webdriver.By.css('h1'));
|
||||
expect(await h1s[0].getText()).toEqual('Actor Form');
|
||||
});
|
||||
|
||||
it('should not display message before submit', async () => {
|
||||
const ele = element(by.css('h2'));
|
||||
expect(await ele.isDisplayed()).toBe(false);
|
||||
const h2s = await driver.findElements(webdriver.By.css('h2'));
|
||||
expect(h2s.length === 0 || !(await h2s[0].isDisplayed())).toBe(true);
|
||||
});
|
||||
|
||||
it('should hide form after submit', async () => {
|
||||
const ele = element.all(by.css('h1')).get(0);
|
||||
const ele = (await driver.findElements(webdriver.By.css('h1')))[0];
|
||||
expect(await ele.isDisplayed()).toBe(true);
|
||||
|
||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
||||
const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0];
|
||||
await b.click();
|
||||
expect(await ele.isDisplayed()).toBe(false);
|
||||
const h1s = await driver.findElements(webdriver.By.css('h1'));
|
||||
expect(h1s.length === 0 || !(await h1s[0].isDisplayed())).toBe(true);
|
||||
});
|
||||
|
||||
it('should display message after submit', async () => {
|
||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
||||
const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0];
|
||||
await b.click();
|
||||
expect(await element(by.css('h2')).getText()).toContain('You submitted the following');
|
||||
expect(await (await driver.findElement(webdriver.By.css('h2'))).getText()).toContain(
|
||||
'You submitted the following',
|
||||
);
|
||||
});
|
||||
|
||||
it('should hide form after submit', async () => {
|
||||
const studioEle = element.all(by.css('input[name=studio]')).get(0);
|
||||
const studioEle = (await driver.findElements(webdriver.By.css('input[name=studio]')))[0];
|
||||
expect(await studioEle.isDisplayed()).toBe(true);
|
||||
|
||||
const submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
|
||||
const submitButtonEle = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0];
|
||||
await submitButtonEle.click();
|
||||
expect(await studioEle.isDisplayed()).toBe(false);
|
||||
const studioEles = await driver.findElements(webdriver.By.css('input[name=studio]'));
|
||||
expect(studioEles.length === 0 || !(await studioEles[0].isDisplayed())).toBe(true);
|
||||
});
|
||||
|
||||
it('should reflect submitted data after submit', async () => {
|
||||
const studioEle = element.all(by.css('input[name=studio]')).get(0);
|
||||
const studioEle = (await driver.findElements(webdriver.By.css('input[name=studio]')))[0];
|
||||
const value = await studioEle.getAttribute('value');
|
||||
const test = 'testing 1 2 3';
|
||||
const newValue = value + test;
|
||||
@@ -45,12 +54,18 @@ describe('Forms Tests', () => {
|
||||
await studioEle.sendKeys(test);
|
||||
expect(await studioEle.getAttribute('value')).toEqual(newValue);
|
||||
|
||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
||||
const b = (await driver.findElements(webdriver.By.css('button[type=submit]')))[0];
|
||||
await b.click();
|
||||
|
||||
const studioTextEle = element(by.cssContainingText('div', 'Studio'));
|
||||
expect(await studioTextEle.isPresent()).toBe(true, 'cannot locate "Studio" label');
|
||||
const divEle = element(by.cssContainingText('div', newValue));
|
||||
expect(await divEle.isPresent()).toBe(true, `cannot locate div with this text: ${newValue}`);
|
||||
const divs = await driver.findElements(webdriver.By.css('div'));
|
||||
let foundStudio = false;
|
||||
let foundNewValue = false;
|
||||
for (const d of divs) {
|
||||
const text = await d.getText();
|
||||
if (text.includes('Studio')) foundStudio = true;
|
||||
if (text.includes(newValue)) foundNewValue = true;
|
||||
}
|
||||
expect(foundStudio).toBe(true, 'cannot locate "Studio" label');
|
||||
expect(foundNewValue).toBe(true, `cannot locate div with this text: ${newValue}`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,41 +1,51 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('i18n E2E Tests', () => {
|
||||
beforeEach(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display i18n translated welcome: Bonjour !', async () => {
|
||||
expect(await element(by.css('h1')).getText()).toEqual('Bonjour i18n !');
|
||||
expect(await (await driver.findElement(webdriver.By.css('h1'))).getText()).toEqual(
|
||||
'Bonjour i18n !',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the node texts without elements', async () => {
|
||||
expect(await element(by.css('app-root')).getText()).toContain(`Je n'affiche aucun élément`);
|
||||
expect(await (await driver.findElement(webdriver.By.css('app-root'))).getText()).toContain(
|
||||
`Je n'affiche aucun élément`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the translated title attribute', async () => {
|
||||
const title = await element(by.css('img')).getAttribute('title');
|
||||
const title = await (await driver.findElement(webdriver.By.css('img'))).getAttribute('title');
|
||||
expect(title).toBe(`Logo d'Angular`);
|
||||
});
|
||||
|
||||
it('should display the ICU plural expression', async () => {
|
||||
expect(await element.all(by.css('span')).get(0).getText()).toBe(`Mis à jour à l'instant`);
|
||||
const spans = await driver.findElements(webdriver.By.css('span'));
|
||||
expect(await spans[0].getText()).toBe(`Mis à jour à l'instant`);
|
||||
});
|
||||
|
||||
it('should display the ICU select expression', async () => {
|
||||
const selectIcuExp = element.all(by.css('span')).get(1);
|
||||
expect(await selectIcuExp.getText()).toBe(`L'auteur est une femme`);
|
||||
await element.all(by.css('button')).get(2).click();
|
||||
expect(await selectIcuExp.getText()).toBe(`L'auteur est un homme`);
|
||||
const spans = await driver.findElements(webdriver.By.css('span'));
|
||||
const buttons = await driver.findElements(webdriver.By.css('button'));
|
||||
expect(await spans[1].getText()).toBe(`L'auteur est une femme`);
|
||||
await buttons[2].click();
|
||||
expect(await spans[1].getText()).toBe(`L'auteur est un homme`);
|
||||
});
|
||||
|
||||
it('should display the nested expression', async () => {
|
||||
const nestedExp = element.all(by.css('span')).get(2);
|
||||
const incBtn = element.all(by.css('button')).get(0);
|
||||
expect(await nestedExp.getText()).toBe(`Mis à jour: à l'instant`);
|
||||
await incBtn.click();
|
||||
expect(await nestedExp.getText()).toBe(`Mis à jour: il y a une minute`);
|
||||
await incBtn.click();
|
||||
await incBtn.click();
|
||||
await element.all(by.css('button')).get(4).click();
|
||||
expect(await nestedExp.getText()).toBe(`Mis à jour: il y a 3 minutes par autre`);
|
||||
const spans = await driver.findElements(webdriver.By.css('span'));
|
||||
const buttons = await driver.findElements(webdriver.By.css('button'));
|
||||
expect(await spans[2].getText()).toBe(`Mis à jour: à l'instant`);
|
||||
await buttons[0].click();
|
||||
expect(await spans[2].getText()).toBe(`Mis à jour: il y a une minute`);
|
||||
await buttons[0].click();
|
||||
await buttons[0].click();
|
||||
await buttons[4].click();
|
||||
expect(await spans[2].getText()).toBe(`Mis à jour: il y a 3 minutes par autre`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
{
|
||||
"projectType": "i18n",
|
||||
"overrideBoilerplate": [
|
||||
"angular.json"
|
||||
],
|
||||
"overrideBoilerplate": ["angular.json"],
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--protractor-config=e2e/protractor-bazel.conf.js",
|
||||
"--no-webdriver-update",
|
||||
"--port=0"
|
||||
]
|
||||
"args": ["e2e"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
import '@angular/common/locales/global/fr';
|
||||
// #enddocregion global-locale
|
||||
|
||||
import {provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [
|
||||
provideProtractorTestingSupport(), // essential for e2e testing
|
||||
],
|
||||
});
|
||||
bootstrapApplication(AppComponent);
|
||||
|
||||
@@ -1,52 +1,73 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Reactive forms', () => {
|
||||
const nameEditor = element(by.css('app-name-editor'));
|
||||
const profileEditor = element(by.css('app-profile-editor'));
|
||||
const nameEditorButton = element(by.cssContainingText('app-root > nav > button', 'Name Editor'));
|
||||
const profileEditorButton = element(
|
||||
by.cssContainingText('app-root > nav > button', 'Profile Editor'),
|
||||
);
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
const getNameEditor = () => driver.findElement(webdriver.By.css('app-name-editor'));
|
||||
const getProfileEditor = () => driver.findElement(webdriver.By.css('app-profile-editor'));
|
||||
|
||||
const findNavButton = async (text: string) => {
|
||||
const buttons = await driver.findElements(webdriver.By.css('app-root > nav > button'));
|
||||
for (const b of buttons) {
|
||||
if ((await b.getText()).includes(text)) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
throw new Error(`Nav button "${text}" not found`);
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
describe('Name Editor', () => {
|
||||
const nameInput = nameEditor.element(by.css('input'));
|
||||
const updateButton = nameEditor.element(by.buttonText('Update Name'));
|
||||
const nameText = 'John Smith';
|
||||
|
||||
beforeAll(async () => {
|
||||
await nameEditorButton.click();
|
||||
await (await findNavButton('Name Editor')).click();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input'));
|
||||
await nameInput.clear();
|
||||
});
|
||||
|
||||
it('should update the name value when the name control is updated', async () => {
|
||||
const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input'));
|
||||
await nameInput.sendKeys(nameText);
|
||||
|
||||
const value = await nameInput.getAttribute('value');
|
||||
|
||||
expect(value).toBe(nameText);
|
||||
});
|
||||
|
||||
it('should update the name control when the Update Name button is clicked', async () => {
|
||||
const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input'));
|
||||
const updateButton = await (
|
||||
await getNameEditor()
|
||||
).findElement(webdriver.By.xpath('.//button[normalize-space()="Update Name"]'));
|
||||
|
||||
await nameInput.sendKeys(nameText);
|
||||
const value1 = await nameInput.getAttribute('value');
|
||||
|
||||
expect(value1).toBe(nameText);
|
||||
|
||||
await updateButton.click();
|
||||
|
||||
const value2 = await nameInput.getAttribute('value');
|
||||
|
||||
expect(value2).toBe('Nancy');
|
||||
});
|
||||
|
||||
it('should update the displayed control value when the name control updated', async () => {
|
||||
const nameInput = await (await getNameEditor()).findElement(webdriver.By.css('input'));
|
||||
await nameInput.sendKeys(nameText);
|
||||
const valueElement = nameEditor.element(by.cssContainingText('p', 'Value:'));
|
||||
const nameValueElement = await valueElement.getText();
|
||||
|
||||
const paragraphs = await (await getNameEditor()).findElements(webdriver.By.css('p'));
|
||||
let valueElement: webdriver.WebElement | null = null;
|
||||
for (const p of paragraphs) {
|
||||
if ((await p.getText()).includes('Value:')) {
|
||||
valueElement = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const nameValueElement = await valueElement!.getText();
|
||||
const nameValue = nameValueElement.toString().replace('Value: ', '');
|
||||
|
||||
expect(nameValue).toBe(nameText);
|
||||
@@ -54,10 +75,6 @@ describe('Reactive forms', () => {
|
||||
});
|
||||
|
||||
describe('Profile Editor', () => {
|
||||
const firstNameInput = getInput('firstName');
|
||||
const streetInput = getInput('street');
|
||||
const addAliasButton = element(by.buttonText('+ Add another alias'));
|
||||
const updateButton = profileEditor.element(by.buttonText('Update Profile'));
|
||||
const profile: Record<string, string | number> = {
|
||||
firstName: 'John',
|
||||
lastName: 'Smith',
|
||||
@@ -68,26 +85,33 @@ describe('Reactive forms', () => {
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await profileEditorButton.click();
|
||||
await (await findNavButton('Profile Editor')).click();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await browser.get('');
|
||||
await profileEditorButton.click();
|
||||
await driver.get('');
|
||||
await (await findNavButton('Profile Editor')).click();
|
||||
});
|
||||
|
||||
it('should be invalid by default', async () => {
|
||||
expect(await profileEditor.getText()).toContain('Form Status: INVALID');
|
||||
expect(await (await getProfileEditor()).getText()).toContain('Form Status: INVALID');
|
||||
});
|
||||
|
||||
it('should be valid if the First Name is filled in', async () => {
|
||||
const firstNameInput = await getInput('firstName');
|
||||
await firstNameInput.clear();
|
||||
await firstNameInput.sendKeys('John Smith');
|
||||
|
||||
expect(await profileEditor.getText()).toContain('Form Status: VALID');
|
||||
expect(await (await getProfileEditor()).getText()).toContain('Form Status: VALID');
|
||||
});
|
||||
|
||||
it('should update the name when the button is clicked', async () => {
|
||||
const firstNameInput = await getInput('firstName');
|
||||
const streetInput = await getInput('street');
|
||||
const updateButton = await (
|
||||
await getProfileEditor()
|
||||
).findElement(webdriver.By.xpath('.//button[normalize-space()="Update Profile"]'));
|
||||
|
||||
await firstNameInput.clear();
|
||||
await streetInput.clear();
|
||||
await firstNameInput.sendKeys('John');
|
||||
@@ -107,23 +131,42 @@ describe('Reactive forms', () => {
|
||||
});
|
||||
|
||||
it('should add an alias field when the Add Alias button is clicked', async () => {
|
||||
const addAliasButton = await driver.findElement(
|
||||
webdriver.By.xpath('.//button[normalize-space()="+ Add another alias"]'),
|
||||
);
|
||||
await addAliasButton.click();
|
||||
|
||||
const aliasInputs = profileEditor.all(by.cssContainingText('label', 'Alias'));
|
||||
const labels = await (await getProfileEditor()).findElements(webdriver.By.css('label'));
|
||||
const aliasLabels: webdriver.WebElement[] = [];
|
||||
for (const l of labels) {
|
||||
if ((await l.getText()).includes('Alias')) {
|
||||
aliasLabels.push(l);
|
||||
}
|
||||
}
|
||||
|
||||
expect(await aliasInputs.count()).toBe(2);
|
||||
expect(aliasLabels.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should update the displayed form value when form inputs are updated', async () => {
|
||||
const aliasText = 'Johnny';
|
||||
await Promise.all(
|
||||
Object.keys(profile).map((key) => getInput(key).sendKeys(`${profile[key]}`)),
|
||||
);
|
||||
for (const key of Object.keys(profile)) {
|
||||
await (await getInput(key)).sendKeys(`${profile[key]}`);
|
||||
}
|
||||
|
||||
const aliasInput = profileEditor.all(by.css('#alias-0'));
|
||||
const aliasInput = (
|
||||
await (await getProfileEditor()).findElements(webdriver.By.css('#alias-0'))
|
||||
)[0];
|
||||
await aliasInput.sendKeys(aliasText);
|
||||
const formValueElement = profileEditor.all(by.cssContainingText('p', 'Form Value:'));
|
||||
const formValue = await formValueElement.getText();
|
||||
|
||||
const paragraphs = await (await getProfileEditor()).findElements(webdriver.By.css('p'));
|
||||
let formValueElement: webdriver.WebElement | null = null;
|
||||
for (const p of paragraphs) {
|
||||
if ((await p.getText()).includes('Form Value:')) {
|
||||
formValueElement = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const formValue = await formValueElement!.getText();
|
||||
const formJson = JSON.parse(formValue.toString().replace('Form Value:', ''));
|
||||
|
||||
expect(profile['firstName']).toBe(formJson.firstName);
|
||||
@@ -133,6 +176,6 @@ describe('Reactive forms', () => {
|
||||
});
|
||||
|
||||
function getInput(key: string) {
|
||||
return element(by.css(`input[formcontrolname=${key}`));
|
||||
return driver.findElement(webdriver.By.css(`input[formcontrolname=${key}]`));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Routing with Custom Matching', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
it('should display Routing with Custom Matching ', async () => {
|
||||
expect(await element(by.css('h2')).getText()).toEqual('Routing with Custom Matching');
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display Routing with Custom Matching', async () => {
|
||||
expect(await (await driver.findElement(webdriver.By.css('h2'))).getText()).toEqual(
|
||||
'Routing with Custom Matching',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
import {ApplicationConfig} from '@angular/core';
|
||||
import {provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {provideRouter, withComponentInputBinding} from '@angular/router';
|
||||
|
||||
import {routes} from './app.routes';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideRouter(routes, withComponentInputBinding()),
|
||||
provideProtractorTestingSupport(),
|
||||
],
|
||||
providers: [provideRouter(routes, withComponentInputBinding())],
|
||||
};
|
||||
|
||||
@@ -1,36 +1,42 @@
|
||||
import {browser, element, By} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Security E2E Tests', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('sanitizes innerHTML', async () => {
|
||||
const interpolated = element(By.className('e2e-inner-html-interpolated'));
|
||||
const interpolated = await driver.findElement(
|
||||
webdriver.By.className('e2e-inner-html-interpolated'),
|
||||
);
|
||||
expect(await interpolated.getText()).toContain(
|
||||
'Template <script>alert("0wned")</script> <b>Syntax</b>',
|
||||
);
|
||||
const bound = element(By.className('e2e-inner-html-bound'));
|
||||
const bound = await driver.findElement(webdriver.By.className('e2e-inner-html-bound'));
|
||||
expect(await bound.getText()).toContain('Template Syntax');
|
||||
const bold = element(By.css('.e2e-inner-html-bound b'));
|
||||
const bold = await driver.findElement(webdriver.By.css('.e2e-inner-html-bound b'));
|
||||
expect(await bold.getText()).toContain('Syntax');
|
||||
});
|
||||
|
||||
it('escapes untrusted URLs', async () => {
|
||||
const untrustedUrl = element(By.className('e2e-dangerous-url'));
|
||||
const untrustedUrl = await driver.findElement(webdriver.By.className('e2e-dangerous-url'));
|
||||
expect(await untrustedUrl.getAttribute('href')).toMatch(/^unsafe:javascript/);
|
||||
});
|
||||
|
||||
it('binds trusted URLs', async () => {
|
||||
const trustedUrl = element(By.className('e2e-trusted-url'));
|
||||
const trustedUrl = await driver.findElement(webdriver.By.className('e2e-trusted-url'));
|
||||
expect(await trustedUrl.getAttribute('href')).toMatch(/^javascript:alert/);
|
||||
});
|
||||
|
||||
it('escapes untrusted resource URLs', async () => {
|
||||
const iframe = element(By.className('e2e-iframe-untrusted-src'));
|
||||
const iframe = await driver.findElement(webdriver.By.className('e2e-iframe-untrusted-src'));
|
||||
expect(await iframe.getAttribute('src')).toBe('');
|
||||
});
|
||||
|
||||
it('binds trusted resource URLs', async () => {
|
||||
const iframe = element(By.className('e2e-iframe-trusted-src'));
|
||||
const iframe = await driver.findElement(webdriver.By.className('e2e-iframe-trusted-src'));
|
||||
expect(await iframe.getAttribute('src')).toMatch(/^https:\/\/www\.youtube\.com\//);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import {AppPage} from './app.po';
|
||||
import {element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('sw-example App', () => {
|
||||
let page: AppPage;
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeEach(async () => {
|
||||
page = new AppPage();
|
||||
await page.navigateTo();
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('should display welcome message', async () => {
|
||||
expect(await page.getTitleText()).toEqual('Welcome to Service Workers!');
|
||||
expect(await (await driver.findElement(webdriver.By.css('h1, app-root h1'))).getText()).toEqual(
|
||||
'Welcome to Service Workers!',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display the Angular logo', async () => {
|
||||
const logo = element(by.css('img'));
|
||||
expect(await logo.isPresent()).toBe(true);
|
||||
const imgs = await driver.findElements(webdriver.By.css('img'));
|
||||
expect(imgs.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should show a header for the list of links', async () => {
|
||||
const listHeader = element(by.css('app-root > h2'));
|
||||
const listHeader = await driver.findElement(webdriver.By.css('app-root > h2'));
|
||||
expect(await listHeader.getText()).toEqual('Here are some links to help you start:');
|
||||
});
|
||||
|
||||
it('should show a list of links', async () => {
|
||||
const items = await element.all(by.css('ul > li > h2 > a'));
|
||||
const items = await driver.findElements(webdriver.By.css('ul > li > h2 > a'));
|
||||
|
||||
expect(items.length).toBe(4);
|
||||
expect(await items[0].getText()).toBe('Angular Service Worker Intro');
|
||||
@@ -35,8 +35,8 @@ describe('sw-example App', () => {
|
||||
|
||||
// Check for a rejected promise as the service worker is not enabled
|
||||
it('SwUpdate.checkForUpdate() should return a rejected promise', async () => {
|
||||
const button = element(by.css('button'));
|
||||
const rejectMessage = element(by.css('p'));
|
||||
const button = await driver.findElement(webdriver.By.css('button'));
|
||||
const rejectMessage = await driver.findElement(webdriver.By.css('p'));
|
||||
await button.click();
|
||||
expect(await rejectMessage.getText()).toContain('rejected: ');
|
||||
});
|
||||
|
||||
@@ -1,10 +1,25 @@
|
||||
{
|
||||
"projectType": "service-worker",
|
||||
"tests": [
|
||||
{"cmd": "yarn", "args": ["e2e", "--protractor-config=e2e/protractor-bazel.conf.js", "--no-webdriver-update", "--port=0"]},
|
||||
{"cmd": "yarn", "args": ["e2e"]},
|
||||
{"cmd": "yarn", "args": ["build"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw.json'), 'ngsw.json is missing')"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw-worker.js'), 'ngsw-worker.js is missing')"]},
|
||||
{"cmd": "node", "args": ["--eval", "assert(require('./package.json').dependencies['@angular/service-worker'], '@angular/service-worker is missing')"]}
|
||||
{
|
||||
"cmd": "node",
|
||||
"args": ["--eval", "assert(fs.existsSync('./dist/ngsw.json'), 'ngsw.json is missing')"]
|
||||
},
|
||||
{
|
||||
"cmd": "node",
|
||||
"args": [
|
||||
"--eval",
|
||||
"assert(fs.existsSync('./dist/ngsw-worker.js'), 'ngsw-worker.js is missing')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cmd": "node",
|
||||
"args": [
|
||||
"--eval",
|
||||
"assert(require('./package.json').dependencies['@angular/service-worker'], '@angular/service-worker is missing')"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [
|
||||
provideProtractorTestingSupport(), // essential for e2e testing
|
||||
],
|
||||
});
|
||||
bootstrapApplication(AppComponent);
|
||||
|
||||
@@ -1,48 +1,73 @@
|
||||
import {browser, element, by} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Structural Directives', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
beforeAll(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
it('first div should show hero name with *ngIf', async () => {
|
||||
const allDivs = element.all(by.tagName('div'));
|
||||
expect(await allDivs.get(0).getText()).toEqual('Dr. Nice');
|
||||
const allDivs = await driver.findElements(webdriver.By.css('div'));
|
||||
expect(await allDivs[0].getText()).toEqual('Dr. Nice');
|
||||
});
|
||||
|
||||
it('first li should show hero name with *ngFor', async () => {
|
||||
const allLis = element.all(by.tagName('li'));
|
||||
expect(await allLis.get(0).getText()).toEqual('Dr. Nice');
|
||||
const allLis = await driver.findElements(webdriver.By.css('li'));
|
||||
expect(await allLis[0].getText()).toEqual('Dr. Nice');
|
||||
});
|
||||
|
||||
it('ngSwitch have two <happy-hero> instances', async () => {
|
||||
const happyHeroEls = element.all(by.tagName('app-happy-hero'));
|
||||
expect(await happyHeroEls.count()).toEqual(2);
|
||||
const happyHeroEls = await driver.findElements(webdriver.By.css('app-happy-hero'));
|
||||
expect(happyHeroEls.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should toggle *ngIf="hero" with a button', async () => {
|
||||
const toggleHeroButton = element.all(by.cssContainingText('button', 'Toggle hero')).get(0);
|
||||
const paragraph = element.all(by.cssContainingText('p', 'I turned the corner'));
|
||||
expect(await paragraph.get(0).getText()).toContain('I waved');
|
||||
await toggleHeroButton.click();
|
||||
expect(await paragraph.get(0).getText()).not.toContain('I waved');
|
||||
const buttons = await driver.findElements(webdriver.By.css('button'));
|
||||
let toggleHeroButton: webdriver.WebElement | null = null;
|
||||
for (const b of buttons) {
|
||||
if ((await b.getText()).includes('Toggle hero')) {
|
||||
toggleHeroButton = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const paragraphs = await driver.findElements(webdriver.By.css('p'));
|
||||
let paragraph: webdriver.WebElement | null = null;
|
||||
for (const p of paragraphs) {
|
||||
if ((await p.getText()).includes('I turned the corner')) {
|
||||
paragraph = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
expect(await paragraph!.getText()).toContain('I waved');
|
||||
await toggleHeroButton!.click();
|
||||
expect(await paragraph!.getText()).not.toContain('I waved');
|
||||
});
|
||||
|
||||
it('appUnless should show 3 paragraph (A)s and (B)s at the start', async () => {
|
||||
const paragraph = element.all(by.css('p.unless'));
|
||||
expect(await paragraph.count()).toEqual(3);
|
||||
const paragraph = await driver.findElements(webdriver.By.css('p.unless'));
|
||||
expect(paragraph.length).toEqual(3);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
expect(await paragraph.get(i).getText()).toContain('(A)');
|
||||
expect(await paragraph[i].getText()).toContain('(A)');
|
||||
}
|
||||
});
|
||||
|
||||
it('appUnless should show 1 paragraph (B) after toggling condition', async () => {
|
||||
const toggleConditionButton = element
|
||||
.all(by.cssContainingText('button', 'Toggle condition'))
|
||||
.get(0);
|
||||
const paragraph = element.all(by.css('p.unless'));
|
||||
const buttons = await driver.findElements(webdriver.By.css('button'));
|
||||
let toggleConditionButton: webdriver.WebElement | null = null;
|
||||
for (const b of buttons) {
|
||||
if ((await b.getText()).includes('Toggle condition')) {
|
||||
toggleConditionButton = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await toggleConditionButton.click();
|
||||
await toggleConditionButton!.click();
|
||||
|
||||
expect(await paragraph.count()).toEqual(1);
|
||||
expect(await paragraph.get(0).getText()).toContain('(B)');
|
||||
const paragraph = await driver.findElements(webdriver.By.css('p.unless'));
|
||||
expect(paragraph.length).toEqual(1);
|
||||
expect(await paragraph[0].getText()).toContain('(B)');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app/app.component';
|
||||
|
||||
bootstrapApplication(AppComponent, {
|
||||
providers: [provideProtractorTestingSupport()],
|
||||
}).catch((err) => console.error(err));
|
||||
bootstrapApplication(AppComponent).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import {browser, element, by, Key, ExpectedConditions} from 'protractor';
|
||||
import * as webdriver from 'selenium-webdriver';
|
||||
|
||||
describe('Angular v21 World', () => {
|
||||
beforeEach(() => browser.get(''));
|
||||
let driver: webdriver.WebDriver;
|
||||
|
||||
const isPresent = async (locator: webdriver.Locator) => {
|
||||
const els = await driver.findElements(locator);
|
||||
return els.length > 0;
|
||||
};
|
||||
|
||||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get('');
|
||||
});
|
||||
|
||||
async function getCharacterPosition(): Promise<{x: string; y: string}> {
|
||||
const character = element(by.css('.character'));
|
||||
const character = await driver.findElement(webdriver.By.css('.character'));
|
||||
const left = await character.getCssValue('left');
|
||||
const top = await character.getCssValue('top');
|
||||
return {x: left, y: top};
|
||||
@@ -12,31 +23,33 @@ describe('Angular v21 World', () => {
|
||||
|
||||
it('should display the initial game state correctly', async () => {
|
||||
// Character is visible
|
||||
expect(await element(by.css('.character')).isDisplayed()).toBe(true);
|
||||
expect(await (await driver.findElement(webdriver.By.css('.character'))).isDisplayed()).toBe(
|
||||
true,
|
||||
);
|
||||
|
||||
// Info sign is shown with welcome message
|
||||
const infoSign = element(by.css('.info-sign'));
|
||||
const infoSign = await driver.findElement(webdriver.By.css('.info-sign'));
|
||||
expect(await infoSign.isDisplayed()).toBe(true);
|
||||
expect(await infoSign.getAttribute('src')).toContain('welcome-sign.png');
|
||||
|
||||
// D-pad is visible
|
||||
expect(await element(by.css('.d-pad')).isDisplayed()).toBe(true);
|
||||
expect(await (await driver.findElement(webdriver.By.css('.d-pad'))).isDisplayed()).toBe(true);
|
||||
|
||||
// Explore button is not visible
|
||||
expect(await element(by.css('.explore-button')).isPresent()).toBe(false);
|
||||
expect(await isPresent(webdriver.By.css('.explore-button'))).toBe(false);
|
||||
|
||||
// No keys are present
|
||||
expect(await element.all(by.css('.key-icon')).count()).toBe(0);
|
||||
expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should move the character with the D-pad buttons', async () => {
|
||||
const initialPosition = await getCharacterPosition();
|
||||
const leftButton = element(by.css('.d-pad-button.left'));
|
||||
const leftButton = await driver.findElement(webdriver.By.css('.d-pad-button.left'));
|
||||
|
||||
// Hold the button down for a short period to simulate walking
|
||||
await browser.actions().mouseDown(leftButton).perform();
|
||||
await browser.sleep(200);
|
||||
await browser.actions().mouseUp(leftButton).perform();
|
||||
await driver.actions().move({origin: leftButton}).press().perform();
|
||||
await sleep(200);
|
||||
await driver.actions().release().perform();
|
||||
|
||||
const newPosition = await getCharacterPosition();
|
||||
expect(newPosition.x).not.toEqual(initialPosition.x);
|
||||
@@ -46,127 +59,146 @@ describe('Angular v21 World', () => {
|
||||
const initialPosition = await getCharacterPosition();
|
||||
|
||||
// Send arrow key press
|
||||
await browser.actions().sendKeys(Key.ARROW_RIGHT).perform();
|
||||
await browser.sleep(200); // Allow time for movement
|
||||
await browser.actions().sendKeys(Key.NULL).perform(); // Release key
|
||||
const body = await driver.findElement(webdriver.By.css('body'));
|
||||
await body.sendKeys(webdriver.Key.ARROW_RIGHT);
|
||||
await sleep(200);
|
||||
|
||||
const newPosition = await getCharacterPosition();
|
||||
expect(newPosition.x).not.toEqual(initialPosition.x);
|
||||
});
|
||||
|
||||
it('should show explore button, open dialog, and collect a key when a destination is reached', async () => {
|
||||
const body = element(by.css('body'));
|
||||
const exploreButton = element(by.css('.explore-button'));
|
||||
const dialog = element(by.css('.dialog-overlay'));
|
||||
const body = await driver.findElement(webdriver.By.css('body'));
|
||||
|
||||
// Move left until we reach the Palm Tree destination
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await body.sendKeys(Key.ARROW_LEFT);
|
||||
await browser.sleep(100);
|
||||
await body.sendKeys(webdriver.Key.ARROW_LEFT);
|
||||
await sleep(100);
|
||||
}
|
||||
|
||||
// Wait for the explore button to appear and check info sign
|
||||
await browser.wait(ExpectedConditions.visibilityOf(exploreButton), 5000);
|
||||
const exploreButtonLocator = webdriver.By.css('.explore-button');
|
||||
await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000);
|
||||
const exploreButton = await driver.findElement(exploreButtonLocator);
|
||||
expect(await exploreButton.isDisplayed()).toBe(true);
|
||||
expect(await element(by.css('.info-sign')).getAttribute('src')).toContain('enter-sign.png');
|
||||
expect(
|
||||
await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'),
|
||||
).toContain('enter-sign.png');
|
||||
|
||||
// Click explore button to open dialog
|
||||
await exploreButton.click();
|
||||
await browser.wait(ExpectedConditions.visibilityOf(dialog), 1000);
|
||||
const dialogLocator = webdriver.By.css('.dialog-overlay');
|
||||
await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000);
|
||||
const dialog = await driver.findElement(dialogLocator);
|
||||
expect(await dialog.isDisplayed()).toBe(true);
|
||||
expect(await dialog.element(by.css('h2')).getText()).toEqual("What's new in Angular AI");
|
||||
expect(await (await dialog.findElement(webdriver.By.css('h2'))).getText()).toEqual(
|
||||
"What's new in Angular AI",
|
||||
);
|
||||
|
||||
// Close the dialog
|
||||
await dialog.element(by.css('.close-button')).click();
|
||||
await browser.wait(ExpectedConditions.invisibilityOf(dialog), 1000);
|
||||
expect(await dialog.isPresent()).toBe(false);
|
||||
await (await dialog.findElement(webdriver.By.css('.close-button'))).click();
|
||||
await driver.wait(async () => !(await isPresent(dialogLocator)), 1000);
|
||||
expect(await isPresent(dialogLocator)).toBe(false);
|
||||
|
||||
// Check that one key has been collected
|
||||
expect(await element.all(by.css('.key-icon')).count()).toBe(1);
|
||||
expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(1);
|
||||
});
|
||||
|
||||
it('should show entry denied at castle without all keys', async () => {
|
||||
const body = element(by.css('body'));
|
||||
const exploreButton = element(by.css('.explore-button'));
|
||||
const body = await driver.findElement(webdriver.By.css('body'));
|
||||
|
||||
// Move to a position near the castle without collecting keys
|
||||
for (let i = 0; i < 20; i++) (await body.sendKeys(Key.ARROW_RIGHT), await browser.sleep(100));
|
||||
for (let i = 0; i < 20; i++) (await body.sendKeys(Key.ARROW_DOWN), await browser.sleep(100));
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await body.sendKeys(webdriver.Key.ARROW_RIGHT);
|
||||
await sleep(100);
|
||||
}
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await body.sendKeys(webdriver.Key.ARROW_DOWN);
|
||||
await sleep(100);
|
||||
}
|
||||
|
||||
await browser.sleep(1000); // Settle
|
||||
await sleep(1000); // Settle
|
||||
|
||||
// Check that the entry denied sign is shown and the button is not present
|
||||
expect(await element(by.css('.info-sign')).getAttribute('src')).toContain(
|
||||
'entry-denied-sign.png',
|
||||
);
|
||||
expect(await exploreButton.isPresent()).toBe(false);
|
||||
expect(
|
||||
await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'),
|
||||
).toContain('entry-denied-sign.png');
|
||||
expect(await isPresent(webdriver.By.css('.explore-button'))).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle the full game flow and show congrats state', async () => {
|
||||
const body = element(by.css('body'));
|
||||
const exploreButton = element(by.css('.explore-button'));
|
||||
const dialog = element(by.css('.dialog-overlay'));
|
||||
const keys = element.all(by.css('.key-icon'));
|
||||
const mascot = element(by.css('.mascot-icon'));
|
||||
const body = await driver.findElement(webdriver.By.css('body'));
|
||||
const exploreButtonLocator = webdriver.By.css('.explore-button');
|
||||
const dialogLocator = webdriver.By.css('.dialog-overlay');
|
||||
const mascotLocator = webdriver.By.css('.mascot-icon');
|
||||
|
||||
// **Navigate to Palm Tree (d1) and collect the first key**
|
||||
for (let i = 0; i < 20; i++) {
|
||||
await body.sendKeys(Key.ARROW_LEFT);
|
||||
await browser.sleep(100);
|
||||
await body.sendKeys(webdriver.Key.ARROW_LEFT);
|
||||
await sleep(100);
|
||||
}
|
||||
await browser.wait(ExpectedConditions.visibilityOf(exploreButton), 5000);
|
||||
await exploreButton.click();
|
||||
await browser.wait(ExpectedConditions.visibilityOf(dialog), 1000);
|
||||
await dialog.element(by.css('.close-button')).click();
|
||||
await browser.wait(ExpectedConditions.invisibilityOf(dialog), 1000);
|
||||
expect(await keys.count()).toBe(1);
|
||||
await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000);
|
||||
await (await driver.findElement(exploreButtonLocator)).click();
|
||||
await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000);
|
||||
let dialog = await driver.findElement(dialogLocator);
|
||||
await (await dialog.findElement(webdriver.By.css('.close-button'))).click();
|
||||
await driver.wait(async () => !(await isPresent(dialogLocator)), 1000);
|
||||
expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(1);
|
||||
|
||||
// **Navigate to Red Door (d2) and collect the second key**
|
||||
for (let i = 0; i < 15; i++) {
|
||||
await body.sendKeys(Key.ARROW_UP);
|
||||
await browser.sleep(100);
|
||||
await body.sendKeys(webdriver.Key.ARROW_UP);
|
||||
await sleep(100);
|
||||
}
|
||||
await browser.wait(ExpectedConditions.visibilityOf(exploreButton), 5000);
|
||||
await exploreButton.click();
|
||||
await browser.wait(ExpectedConditions.visibilityOf(dialog), 1000);
|
||||
await dialog.element(by.css('.close-button')).click();
|
||||
await browser.wait(ExpectedConditions.invisibilityOf(dialog), 1000);
|
||||
expect(await keys.count()).toBe(2);
|
||||
await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000);
|
||||
await (await driver.findElement(exploreButtonLocator)).click();
|
||||
await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000);
|
||||
dialog = await driver.findElement(dialogLocator);
|
||||
await (await dialog.findElement(webdriver.By.css('.close-button'))).click();
|
||||
await driver.wait(async () => !(await isPresent(dialogLocator)), 1000);
|
||||
expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(2);
|
||||
|
||||
// **Navigate to Volcano (d3) and collect the third key**
|
||||
for (let i = 0; i < 25; i++) {
|
||||
await body.sendKeys(Key.ARROW_RIGHT);
|
||||
await browser.sleep(100);
|
||||
await body.sendKeys(webdriver.Key.ARROW_RIGHT);
|
||||
await sleep(100);
|
||||
}
|
||||
await browser.wait(ExpectedConditions.visibilityOf(exploreButton), 5000);
|
||||
await exploreButton.click();
|
||||
await browser.wait(ExpectedConditions.visibilityOf(dialog), 1000);
|
||||
await dialog.element(by.css('.close-button')).click();
|
||||
await browser.wait(ExpectedConditions.invisibilityOf(dialog), 1000);
|
||||
expect(await keys.count()).toBe(3);
|
||||
await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000);
|
||||
await (await driver.findElement(exploreButtonLocator)).click();
|
||||
await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000);
|
||||
dialog = await driver.findElement(dialogLocator);
|
||||
await (await dialog.findElement(webdriver.By.css('.close-button'))).click();
|
||||
await driver.wait(async () => !(await isPresent(dialogLocator)), 1000);
|
||||
expect((await driver.findElements(webdriver.By.css('.key-icon'))).length).toBe(3);
|
||||
|
||||
// **Navigate to Castle (d4) with all keys**
|
||||
for (let i = 0; i < 15; i++) {
|
||||
await body.sendKeys(Key.ARROW_DOWN);
|
||||
await browser.sleep(100);
|
||||
await body.sendKeys(webdriver.Key.ARROW_DOWN);
|
||||
await sleep(100);
|
||||
}
|
||||
await browser.sleep(1000); // Wait for character to settle
|
||||
await sleep(1000); // Wait for character to settle
|
||||
|
||||
// Check for correct sign and button visibility
|
||||
expect(await element(by.css('.info-sign')).getAttribute('src')).toContain('castle-sign.png');
|
||||
await browser.wait(ExpectedConditions.visibilityOf(exploreButton), 5000);
|
||||
expect(
|
||||
await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'),
|
||||
).toContain('castle-sign.png');
|
||||
await driver.wait(webdriver.until.elementLocated(exploreButtonLocator), 5000);
|
||||
|
||||
// **Open Castle dialog, close it, and see mascot and final sign**
|
||||
await exploreButton.click();
|
||||
await browser.wait(ExpectedConditions.visibilityOf(dialog), 1000);
|
||||
await dialog.element(by.css('.close-button')).click();
|
||||
await browser.wait(ExpectedConditions.invisibilityOf(dialog), 1000);
|
||||
await (await driver.findElement(exploreButtonLocator)).click();
|
||||
await driver.wait(webdriver.until.elementLocated(dialogLocator), 1000);
|
||||
dialog = await driver.findElement(dialogLocator);
|
||||
await (await dialog.findElement(webdriver.By.css('.close-button'))).click();
|
||||
await driver.wait(async () => !(await isPresent(dialogLocator)), 1000);
|
||||
|
||||
// Mascot appears
|
||||
await browser.wait(ExpectedConditions.visibilityOf(mascot), 1000);
|
||||
await driver.wait(webdriver.until.elementLocated(mascotLocator), 1000);
|
||||
const mascot = await driver.findElement(mascotLocator);
|
||||
expect(await mascot.isDisplayed()).toBe(true);
|
||||
|
||||
// Congrats sign appears
|
||||
expect(await element(by.css('.info-sign')).getAttribute('src')).toContain('congrats-sign.png');
|
||||
expect(
|
||||
await (await driver.findElement(webdriver.By.css('.info-sign'))).getAttribute('src'),
|
||||
).toContain('congrats-sign.png');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"tests": [
|
||||
{"cmd": "yarn", "args": ["test", "--browsers=ChromeHeadlessNoSandbox", "--no-watch"]},
|
||||
{"cmd": "yarn", "args": ["e2e", "--configuration=production", "--protractor-config=e2e/protractor-bazel.conf.js", "--no-webdriver-update", "--port=0"]}
|
||||
{"cmd": "yarn", "args": ["e2e", "--configuration=production"]}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [
|
||||
provideProtractorTestingSupport(), // essential for e2e testing
|
||||
],
|
||||
});
|
||||
bootstrapApplication(App);
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
|
||||
bootstrapApplication(App, {providers: [provideProtractorTestingSupport()]}).catch((err) =>
|
||||
console.error(err),
|
||||
);
|
||||
bootstrapApplication(App).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import routeConfig from './app/routes';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport(), provideRouter(routeConfig)],
|
||||
providers: [provideRouter(routeConfig)],
|
||||
}).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import routeConfig from './app/routes';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport(), provideRouter(routeConfig)],
|
||||
providers: [provideRouter(routeConfig)],
|
||||
}).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import routeConfig from './app/routes';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport(), provideRouter(routeConfig)],
|
||||
providers: [provideRouter(routeConfig)],
|
||||
}).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import routeConfig from './app/routes';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport(), provideRouter(routeConfig)],
|
||||
providers: [provideRouter(routeConfig)],
|
||||
}).catch((err) => console.error(err));
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
/*
|
||||
* Protractor support is deprecated in Angular.
|
||||
* Protractor is used in this example for compatibility with Angular documentation tools.
|
||||
*/
|
||||
import {bootstrapApplication, provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {App} from './app/app';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import routeConfig from './app/routes';
|
||||
|
||||
bootstrapApplication(App, {
|
||||
providers: [provideProtractorTestingSupport(), provideRouter(routeConfig)],
|
||||
providers: [provideRouter(routeConfig)],
|
||||
}).catch((err) => console.error(err));
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
"lib": ["es2015"],
|
||||
"types": ["node", "jasmine", "selenium-webdriver"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,9 +14,9 @@ load("//tools/bazel:esbuild.bzl", _esbuild = "esbuild", _esbuild_checked_in = "e
|
||||
load("//tools/bazel:jasmine_test.bzl", _angular_jasmine_test = "angular_jasmine_test", _jasmine_test = "jasmine_test", _zone_compatible_jasmine_test = "zone_compatible_jasmine_test", _zoneless_jasmine_test = "zoneless_jasmine_test")
|
||||
load("//tools/bazel:js_defs.bzl", _js_binary = "js_binary", _js_run_binary = "js_run_binary", _js_test = "js_test")
|
||||
load("//tools/bazel:npm_packages.bzl", _ng_package = "ng_package", _npm_package = "npm_package")
|
||||
load("//tools/bazel:webdriver_test.bzl", _webdriver_test = "webdriver_test")
|
||||
load("//tools/bazel:tsec.bzl", _tsec_test = "tsec_test")
|
||||
load("//tools/bazel:web_test.bzl", _ng_web_test_suite = "ng_web_test_suite", _web_test = "web_test", _zoneless_web_test_suite = "zoneless_web_test_suite")
|
||||
load("//tools/bazel:webdriver_test.bzl", _webdriver_test = "webdriver_test")
|
||||
|
||||
extract_types = _extract_types
|
||||
esbuild = _esbuild
|
||||
|
||||
Reference in New Issue
Block a user