From e120d2830b2b9d1b1e09436ed7d6a0939fde5d76 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 14 Aug 2026 09:23:04 +0200 Subject: [PATCH] build: switch adev tests away from protractor Reworks the tests in adev not to depend on Protractor. (cherry picked from commit 7b74bee5b4485b2a42198db115abcfd5de103c71) --- .../accessibility/e2e/src/app.e2e-spec.ts | 23 +- .../examples/accessibility/src/main.ts | 6 +- .../e2e/src/app.e2e-spec.ts | 15 +- .../example-config.json | 27 +- .../angular-compiler-options/src/main.ts | 6 +- .../animations/e2e/src/app.e2e-spec.ts | 132 +++---- .../examples/animations/e2e/src/auto.po.ts | 20 +- .../animations/e2e/src/enter-leave.po.ts | 20 +- .../animations/e2e/src/filter-stagger.po.ts | 21 +- .../animations/e2e/src/hero-groups.ts | 20 +- .../animations/e2e/src/open-close.po.ts | 30 +- .../animations/e2e/src/querying.po.ts | 16 +- .../animations/e2e/src/status-slider.po.ts | 21 +- .../examples/animations/e2e/src/toggle.po.ts | 29 +- .../examples/animations/e2e/src/util.ts | 25 +- .../examples/animations/src/app/app.config.ts | 8 +- .../e2e/src/app.e2e-spec.ts | 28 +- .../examples/attribute-directives/src/main.ts | 6 +- .../e2e/src/app.e2e-spec.ts | 54 ++- .../examples/built-in-directives/src/main.ts | 6 +- .../dynamic-form/e2e/src/app.e2e-spec.ts | 31 +- .../content/examples/dynamic-form/src/main.ts | 6 +- .../examples/elements/e2e/src/app.e2e-spec.ts | 82 ++-- .../src/content/examples/elements/src/main.ts | 6 +- .../form-validation/e2e/src/app.e2e-spec.ts | 361 +++++++++--------- .../forms-overview/e2e/src/app.e2e-spec.ts | 13 +- .../forms-overview/example-config.json | 2 +- .../examples/forms/e2e/src/app.e2e-spec.ts | 53 ++- .../examples/i18n/e2e/src/app.e2e-spec.ts | 48 ++- .../content/examples/i18n/example-config.json | 11 +- adev/src/content/examples/i18n/src/main.ts | 7 +- .../reactive-forms/e2e/src/app.e2e-spec.ts | 113 ++++-- .../e2e/src/app.e2e-spec.ts | 14 +- .../src/app/app.config.ts | 6 +- .../examples/security/e2e/src/app.e2e-spec.ts | 24 +- .../src/content/examples/security/src/main.ts | 6 +- .../e2e/src/app.e2e-spec.ts | 24 +- .../example-config.json | 23 +- .../src/main.ts | 8 +- .../e2e/src/app.e2e-spec.ts | 71 ++-- .../structural-directives/src/main.ts | 6 +- .../v21-game-world/e2e/src/app.e2e-spec.ts | 186 +++++---- .../v21-game-world/example-config.json | 2 +- .../examples/v21-game-world/src/main.ts | 8 +- .../steps/01-hello-world/src/main.ts | 10 +- .../first-app/steps/02-Home/src/main.ts | 10 +- .../steps/03-HousingLocation/src/main.ts | 10 +- .../first-app/steps/04-interfaces/src/main.ts | 10 +- .../first-app/steps/05-inputs/src/main.ts | 10 +- .../steps/06-property-binding/src/main.ts | 10 +- .../07-dynamic-template-values/src/main.ts | 10 +- .../first-app/steps/08-ngFor/src/main.ts | 10 +- .../first-app/steps/09-services/src/main.ts | 10 +- .../first-app/steps/10-routing/src/main.ts | 10 +- .../steps/11-details-page/src/main.ts | 8 +- .../first-app/steps/12-forms/src/main.ts | 8 +- .../first-app/steps/13-search/src/main.ts | 8 +- .../first-app/steps/14-http/src-final/main.ts | 8 +- .../first-app/steps/14-http/src/main.ts | 8 +- packages/examples/upgrade/tsconfig-e2e.json | 2 +- tools/defaults.bzl | 2 +- 61 files changed, 924 insertions(+), 844 deletions(-) diff --git a/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts index d135719f49a..2b66e003610 100644 --- a/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/accessibility/e2e/src/app.e2e-spec.ts @@ -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'); }); }); diff --git a/adev/src/content/examples/accessibility/src/main.ts b/adev/src/content/examples/accessibility/src/main.ts index 6fc5c42c4a3..9f16c6cce60 100644 --- a/adev/src/content/examples/accessibility/src/main.ts +++ b/adev/src/content/examples/accessibility/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts index b614b967aa9..b9f8cc9fa75 100644 --- a/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/angular-compiler-options/e2e/src/app.e2e-spec.ts @@ -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), ); }); }); diff --git a/adev/src/content/examples/angular-compiler-options/example-config.json b/adev/src/content/examples/angular-compiler-options/example-config.json index 58b92eaf03d..a2e5c5f4dd5 100644 --- a/adev/src/content/examples/angular-compiler-options/example-config.json +++ b/adev/src/content/examples/angular-compiler-options/example-config.json @@ -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" - ] - } - ] - } - \ No newline at end of file + "projectType": "cli", + "overrideBoilerplate": ["tsconfig.json", "tsconfig.app.json"], + "tests": [ + { + "cmd": "yarn", + "args": ["e2e"] + } + ] +} diff --git a/adev/src/content/examples/angular-compiler-options/src/main.ts b/adev/src/content/examples/angular-compiler-options/src/main.ts index 6fc5c42c4a3..9f16c6cce60 100644 --- a/adev/src/content/examples/angular-compiler-options/src/main.ts +++ b/adev/src/content/examples/angular-compiler-options/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts index 7d897afbb99..9182cceb269 100644 --- a/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/animations/e2e/src/app.e2e-spec.ts @@ -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 diff --git a/adev/src/content/examples/animations/e2e/src/auto.po.ts b/adev/src/content/examples/animations/e2e/src/auto.po.ts index defd4424669..427321bff16 100644 --- a/adev/src/content/examples/animations/e2e/src/auto.po.ts +++ b/adev/src/content/examples/animations/e2e/src/auto.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts b/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts index 00342e245b2..ce5b176f65c 100644 --- a/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts +++ b/adev/src/content/examples/animations/e2e/src/enter-leave.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts b/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts index f64cfa5a7dd..1f44e3d7384 100644 --- a/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts +++ b/adev/src/content/examples/animations/e2e/src/filter-stagger.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/hero-groups.ts b/adev/src/content/examples/animations/e2e/src/hero-groups.ts index 60f656f03d0..227a95dc544 100644 --- a/adev/src/content/examples/animations/e2e/src/hero-groups.ts +++ b/adev/src/content/examples/animations/e2e/src/hero-groups.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/open-close.po.ts b/adev/src/content/examples/animations/e2e/src/open-close.po.ts index 2a1f3743d1f..292db95d9ed 100644 --- a/adev/src/content/examples/animations/e2e/src/open-close.po.ts +++ b/adev/src/content/examples/animations/e2e/src/open-close.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/querying.po.ts b/adev/src/content/examples/animations/e2e/src/querying.po.ts index 8dc04b90b5e..aa83ee5565b 100644 --- a/adev/src/content/examples/animations/e2e/src/querying.po.ts +++ b/adev/src/content/examples/animations/e2e/src/querying.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/status-slider.po.ts b/adev/src/content/examples/animations/e2e/src/status-slider.po.ts index 07a31b2c781..a498689e131 100644 --- a/adev/src/content/examples/animations/e2e/src/status-slider.po.ts +++ b/adev/src/content/examples/animations/e2e/src/status-slider.po.ts @@ -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')); } diff --git a/adev/src/content/examples/animations/e2e/src/toggle.po.ts b/adev/src/content/examples/animations/e2e/src/toggle.po.ts index a47600d5f68..454782e59ba 100644 --- a/adev/src/content/examples/animations/e2e/src/toggle.po.ts +++ b/adev/src/content/examples/animations/e2e/src/toggle.po.ts @@ -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]; } diff --git a/adev/src/content/examples/animations/e2e/src/util.ts b/adev/src/content/examples/animations/e2e/src/util.ts index 20ceffbf5e0..c10f9553b00 100644 --- a/adev/src/content/examples/animations/e2e/src/util.ts +++ b/adev/src/content/examples/animations/e2e/src/util.ts @@ -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 { + 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}]`)); } diff --git a/adev/src/content/examples/animations/src/app/app.config.ts b/adev/src/content/examples/animations/src/app/app.config.ts index a6a8cd4a93c..ba937fe087f 100644 --- a/adev/src/content/examples/animations/src/app/app.config.ts +++ b/adev/src/content/examples/animations/src/app/app.config.ts @@ -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()], }; diff --git a/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts index f4950adc2e4..97da4f1e5c8 100644 --- a/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/attribute-directives/e2e/src/app.e2e-spec.ts @@ -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); }); }); diff --git a/adev/src/content/examples/attribute-directives/src/main.ts b/adev/src/content/examples/attribute-directives/src/main.ts index f2f107a9eb5..be80503335f 100644 --- a/adev/src/content/examples/attribute-directives/src/main.ts +++ b/adev/src/content/examples/attribute-directives/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts index 886f0c85f13..a99075a0fd9 100644 --- a/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/built-in-directives/e2e/src/app.e2e-spec.ts @@ -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'); diff --git a/adev/src/content/examples/built-in-directives/src/main.ts b/adev/src/content/examples/built-in-directives/src/main.ts index 6fc5c42c4a3..9f16c6cce60 100644 --- a/adev/src/content/examples/built-in-directives/src/main.ts +++ b/adev/src/content/examples/built-in-directives/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts index 25e95778a9c..e3790401adc 100644 --- a/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/dynamic-form/e2e/src/app.e2e-spec.ts @@ -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); }); }); diff --git a/adev/src/content/examples/dynamic-form/src/main.ts b/adev/src/content/examples/dynamic-form/src/main.ts index 3e5e6757a25..7576b324e5f 100644 --- a/adev/src/content/examples/dynamic-form/src/main.ts +++ b/adev/src/content/examples/dynamic-form/src/main.ts @@ -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); diff --git a/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts index f807fdfb476..5424275b548 100644 --- a/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/elements/e2e/src/app.e2e-spec.ts @@ -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); }); }); }); diff --git a/adev/src/content/examples/elements/src/main.ts b/adev/src/content/examples/elements/src/main.ts index f71065c985c..203da19f9f9 100644 --- a/adev/src/content/examples/elements/src/main.ts +++ b/adev/src/content/examples/elements/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts index f6a3dbd3e06..722345924b4 100644 --- a/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/form-validation/e2e/src/app.e2e-spec.ts @@ -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; + actorFormButtons: () => Promise; + 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); + }); + } +}); diff --git a/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts index c7d881f87a8..8daf57e6a84 100644 --- a/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/forms-overview/e2e/src/app.e2e-spec.ts @@ -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', + ); }); }); diff --git a/adev/src/content/examples/forms-overview/example-config.json b/adev/src/content/examples/forms-overview/example-config.json index ccf472031b4..43c84374fb4 100644 --- a/adev/src/content/examples/forms-overview/example-config.json +++ b/adev/src/content/examples/forms-overview/example-config.json @@ -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"]} ] } diff --git a/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts index 09b0c4601bf..b8171053506 100644 --- a/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/forms/e2e/src/app.e2e-spec.ts @@ -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}`); }); }); diff --git a/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts index 4d576a6736f..768e9b9c80a 100644 --- a/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/i18n/e2e/src/app.e2e-spec.ts @@ -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`); }); }); diff --git a/adev/src/content/examples/i18n/example-config.json b/adev/src/content/examples/i18n/example-config.json index 7512bf529d3..19a0fb2a476 100644 --- a/adev/src/content/examples/i18n/example-config.json +++ b/adev/src/content/examples/i18n/example-config.json @@ -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"] } ] } diff --git a/adev/src/content/examples/i18n/src/main.ts b/adev/src/content/examples/i18n/src/main.ts index d34775046de..2f1d0d3ae35 100644 --- a/adev/src/content/examples/i18n/src/main.ts +++ b/adev/src/content/examples/i18n/src/main.ts @@ -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); diff --git a/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts index 5330f5ef3c7..3161eb59ef2 100644 --- a/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/reactive-forms/e2e/src/app.e2e-spec.ts @@ -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 = { 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}]`)); } }); diff --git a/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts index 693d341cd81..1085a2c569a 100644 --- a/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/routing-with-urlmatcher/e2e/src/app.e2e-spec.ts @@ -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', + ); }); }); diff --git a/adev/src/content/examples/routing-with-urlmatcher/src/app/app.config.ts b/adev/src/content/examples/routing-with-urlmatcher/src/app/app.config.ts index d6612156634..edd274e14f4 100644 --- a/adev/src/content/examples/routing-with-urlmatcher/src/app/app.config.ts +++ b/adev/src/content/examples/routing-with-urlmatcher/src/app/app.config.ts @@ -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())], }; diff --git a/adev/src/content/examples/security/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/security/e2e/src/app.e2e-spec.ts index c4d7d1838f1..d2a131ff312 100644 --- a/adev/src/content/examples/security/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/security/e2e/src/app.e2e-spec.ts @@ -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 Syntax', ); - 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\//); }); }); diff --git a/adev/src/content/examples/security/src/main.ts b/adev/src/content/examples/security/src/main.ts index 6fc5c42c4a3..9f16c6cce60 100644 --- a/adev/src/content/examples/security/src/main.ts +++ b/adev/src/content/examples/security/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts index a484ca9fb23..b0d6b47c80c 100755 --- a/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/service-worker-getting-started/e2e/src/app.e2e-spec.ts @@ -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: '); }); diff --git a/adev/src/content/examples/service-worker-getting-started/example-config.json b/adev/src/content/examples/service-worker-getting-started/example-config.json index b7f7d031108..f37d6cafe6d 100644 --- a/adev/src/content/examples/service-worker-getting-started/example-config.json +++ b/adev/src/content/examples/service-worker-getting-started/example-config.json @@ -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')" + ] + } ] } diff --git a/adev/src/content/examples/service-worker-getting-started/src/main.ts b/adev/src/content/examples/service-worker-getting-started/src/main.ts index 52a1ee4382f..44497618a29 100755 --- a/adev/src/content/examples/service-worker-getting-started/src/main.ts +++ b/adev/src/content/examples/service-worker-getting-started/src/main.ts @@ -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); diff --git a/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts index ea1caae4c35..ea6394e21c6 100644 --- a/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/structural-directives/e2e/src/app.e2e-spec.ts @@ -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 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)'); }); }); diff --git a/adev/src/content/examples/structural-directives/src/main.ts b/adev/src/content/examples/structural-directives/src/main.ts index 6fc5c42c4a3..9f16c6cce60 100644 --- a/adev/src/content/examples/structural-directives/src/main.ts +++ b/adev/src/content/examples/structural-directives/src/main.ts @@ -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)); diff --git a/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts b/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts index 2b018bbf1f4..1fd7b079418 100644 --- a/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts +++ b/adev/src/content/examples/v21-game-world/e2e/src/app.e2e-spec.ts @@ -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'); }); }); diff --git a/adev/src/content/examples/v21-game-world/example-config.json b/adev/src/content/examples/v21-game-world/example-config.json index ccf472031b4..43c84374fb4 100644 --- a/adev/src/content/examples/v21-game-world/example-config.json +++ b/adev/src/content/examples/v21-game-world/example-config.json @@ -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"]} ] } diff --git a/adev/src/content/examples/v21-game-world/src/main.ts b/adev/src/content/examples/v21-game-world/src/main.ts index 438d1c34c7e..917e1f40300 100644 --- a/adev/src/content/examples/v21-game-world/src/main.ts +++ b/adev/src/content/examples/v21-game-world/src/main.ts @@ -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); diff --git a/adev/src/content/tutorials/first-app/steps/01-hello-world/src/main.ts b/adev/src/content/tutorials/first-app/steps/01-hello-world/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/01-hello-world/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/01-hello-world/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/02-Home/src/main.ts b/adev/src/content/tutorials/first-app/steps/02-Home/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/02-Home/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/02-Home/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/main.ts b/adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/03-HousingLocation/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/04-interfaces/src/main.ts b/adev/src/content/tutorials/first-app/steps/04-interfaces/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/04-interfaces/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/04-interfaces/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/05-inputs/src/main.ts b/adev/src/content/tutorials/first-app/steps/05-inputs/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/05-inputs/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/05-inputs/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/06-property-binding/src/main.ts b/adev/src/content/tutorials/first-app/steps/06-property-binding/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/06-property-binding/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/06-property-binding/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/main.ts b/adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/07-dynamic-template-values/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/08-ngFor/src/main.ts b/adev/src/content/tutorials/first-app/steps/08-ngFor/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/08-ngFor/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/08-ngFor/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/09-services/src/main.ts b/adev/src/content/tutorials/first-app/steps/09-services/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/09-services/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/09-services/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/10-routing/src/main.ts b/adev/src/content/tutorials/first-app/steps/10-routing/src/main.ts index 4093863e5e3..2d9f9a58c8a 100644 --- a/adev/src/content/tutorials/first-app/steps/10-routing/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/10-routing/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/11-details-page/src/main.ts b/adev/src/content/tutorials/first-app/steps/11-details-page/src/main.ts index a2453b30c08..62869f401f7 100644 --- a/adev/src/content/tutorials/first-app/steps/11-details-page/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/11-details-page/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/12-forms/src/main.ts b/adev/src/content/tutorials/first-app/steps/12-forms/src/main.ts index a2453b30c08..62869f401f7 100644 --- a/adev/src/content/tutorials/first-app/steps/12-forms/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/12-forms/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/13-search/src/main.ts b/adev/src/content/tutorials/first-app/steps/13-search/src/main.ts index a2453b30c08..62869f401f7 100644 --- a/adev/src/content/tutorials/first-app/steps/13-search/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/13-search/src/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/14-http/src-final/main.ts b/adev/src/content/tutorials/first-app/steps/14-http/src-final/main.ts index a2453b30c08..62869f401f7 100644 --- a/adev/src/content/tutorials/first-app/steps/14-http/src-final/main.ts +++ b/adev/src/content/tutorials/first-app/steps/14-http/src-final/main.ts @@ -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)); diff --git a/adev/src/content/tutorials/first-app/steps/14-http/src/main.ts b/adev/src/content/tutorials/first-app/steps/14-http/src/main.ts index a2453b30c08..62869f401f7 100644 --- a/adev/src/content/tutorials/first-app/steps/14-http/src/main.ts +++ b/adev/src/content/tutorials/first-app/steps/14-http/src/main.ts @@ -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)); diff --git a/packages/examples/upgrade/tsconfig-e2e.json b/packages/examples/upgrade/tsconfig-e2e.json index a89494bf90c..72dd77e79f2 100644 --- a/packages/examples/upgrade/tsconfig-e2e.json +++ b/packages/examples/upgrade/tsconfig-e2e.json @@ -4,4 +4,4 @@ "lib": ["es2015"], "types": ["node", "jasmine", "selenium-webdriver"] } -} \ No newline at end of file +} diff --git a/tools/defaults.bzl b/tools/defaults.bzl index 422b9966b48..f78ee5c0719 100644 --- a/tools/defaults.bzl +++ b/tools/defaults.bzl @@ -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