diff --git a/tests/e2e/tests/build/auto-csp.ts b/tests/e2e/tests/build/auto-csp.ts index 1839b160d549..f9e30efe2de9 100644 --- a/tests/e2e/tests/build/auto-csp.ts +++ b/tests/e2e/tests/build/auto-csp.ts @@ -1,9 +1,11 @@ -import assert from 'node:assert'; +import assert from 'node:assert/strict'; +import { setTimeout } from 'node:timers/promises'; import { getGlobalVariable } from '../../utils/env'; import { expectFileToMatch, writeFile, writeMultipleFiles } from '../../utils/fs'; import { findFreePort } from '../../utils/network'; import { execAndWaitForOutputToMatch, ng } from '../../utils/process'; import { updateJsonFile } from '../../utils/project'; +import { executeBrowserTest } from '../../utils/puppeteer'; const CSP_META_TAG = / `, - 'e2e/src/app.e2e-spec.ts': ` - import { browser, by, element } from 'protractor'; - import * as webdriver from 'selenium-webdriver'; - - function allConsoleWarnMessagesAndErrors() { - return browser - .manage() - .logs() - .get('browser') - .then(function (browserLog: any[]) { - const warnMessages: any[] = []; - browserLog.filter((logEntry) => { - const msg = logEntry.message; - console.log('>> ' + msg); - if (logEntry.level.value >= webdriver.logging.Level.INFO.value) { - warnMessages.push(msg); - } - }); - return warnMessages; - }); - } - - describe('Hello world E2E Tests', () => { - beforeAll(async () => { - await browser.waitForAngularEnabled(true); - }); - - it('should display: Welcome and run all scripts in order', async () => { - // Load the page without waiting for Angular since it is not bootstrapped automatically. - await browser.driver.get(browser.baseUrl); - - // Test the contents. - expect(await element(by.css('h1')).getText()).toMatch('Hello'); - - // Make sure all scripts ran and there were no client side errors. - const consoleMessages = await allConsoleWarnMessagesAndErrors(); - expect(consoleMessages.length).toEqual(4); // No additional errors - // Extract just the printed messages from the console data. - const printedMessages = consoleMessages.map(m => m.match(/"(.*?)"/)[1]); - expect(printedMessages).toEqual([ - // All messages printed in order because execution order is preserved. - "Inline Script Head", - "Inline Script Body: 1339", - "First External Script: 1338", - "Second External Script: 1337", - ]); - }); - }); - `, }); async function spawnServer(): Promise { @@ -137,7 +90,49 @@ export default async function () { // Make sure if contains the critical CSS inlining CSP code. await expectFileToMatch('dist/test-project/browser/index.html', 'ngCspMedia'); - // Make sure that our e2e protractor tests run to confirm that our angular project runs. + // Make sure that our e2e tests run to confirm that our angular project runs. const port = await spawnServer(); - await ng('e2e', `--base-url=http://localhost:${port}`, '--dev-server-target='); + await executeBrowserTest({ + baseUrl: `http://localhost:${port}/`, + checkFn: async (page) => { + const warnMessages: string[] = []; + page.on('console', (msg) => { + if (msg.type() === 'warning') { + warnMessages.push(msg.text()); + } + }); + + // Reload to ensure we capture messages from the start if needed, + // although executeBrowserTest already navigated. + await page.reload(); + + // Wait for the expected number of warnings + let retries = 50; + while (warnMessages.length < 4 && retries > 0) { + await setTimeout(100); + retries--; + } + + assert.strictEqual( + warnMessages.length, + 4, + `Expected 4 console warnings, but got ${warnMessages.length}:\n${warnMessages.join('\n')}`, + ); + + const expectedMessages = [ + 'Inline Script Head', + 'Inline Script Body: 1339', + 'First External Script: 1338', + 'Second External Script: 1337', + ]; + + for (let i = 0; i < expectedMessages.length; i++) { + if (!warnMessages[i].includes(expectedMessages[i])) { + assert.fail( + `Expected warning ${i} to include '${expectedMessages[i]}', but got '${warnMessages[i]}'`, + ); + } + } + }, + }); } diff --git a/tests/e2e/tests/build/worker.ts b/tests/e2e/tests/build/worker.ts index 53e60aa34772..be81aae7dfd4 100644 --- a/tests/e2e/tests/build/worker.ts +++ b/tests/e2e/tests/build/worker.ts @@ -8,10 +8,12 @@ import assert from 'node:assert/strict'; import { readdir } from 'node:fs/promises'; +import { setTimeout } from 'node:timers/promises'; import { getGlobalVariable } from '../../utils/env'; import { expectFileToExist, expectFileToMatch, replaceInFile, writeFile } from '../../utils/fs'; import { ng } from '../../utils/process'; import { expectToFail } from '../../utils/utils'; +import { executeBrowserTest } from '../../utils/puppeteer'; export default async function () { const useWebpackBuilder = !getGlobalVariable('argv')['esbuild']; @@ -55,24 +57,32 @@ export default async function () { // https://github.com/angular/protractor/issues/2207 await replaceInFile('src/app/app.ts', 'console.log', 'console.warn'); - await writeFile( - 'e2e/app.e2e-spec.ts', - ` - import { AppPage } from './app.po'; - import { browser, logging } from 'protractor'; - describe('worker bundle', () => { - it('should log worker messages', async () => { - const page = new AppPage();; - page.navigateTo(); - const logs = await browser.manage().logs().get(logging.Type.BROWSER); - expect(logs.length).toEqual(1); - expect(logs[0].message).toContain('page got message: worker response to hello'); + await executeBrowserTest({ + checkFn: async (page) => { + const messages: string[] = []; + page.on('console', (msg) => { + messages.push(msg.text()); }); - }); - `, - ); - await ng('e2e'); + // Reload to ensure we capture messages from the start if needed, + // although executeBrowserTest already navigated. + await page.reload(); + + // Wait for the worker message + let retries = 50; + while ( + !messages.some((m) => m.includes('page got message: worker response to hello')) && + retries > 0 + ) { + await setTimeout(100); + retries--; + } + + if (!messages.some((m) => m.includes('page got message: worker response to hello'))) { + assert.fail(`Expected worker message not found in console. Got:\n${messages.join('\n')}`); + } + }, + }); } async function getWorkerOutputFile(useWebpackBuilder: boolean): Promise { diff --git a/tests/e2e/tests/misc/trusted-types.ts b/tests/e2e/tests/misc/trusted-types.ts index 325ee521fe6d..21deb03223dd 100644 --- a/tests/e2e/tests/misc/trusted-types.ts +++ b/tests/e2e/tests/misc/trusted-types.ts @@ -6,9 +6,11 @@ * found in the LICENSE file at https://angular.dev/license */ -import { replaceInFile, writeFile } from '../../utils/fs'; +import assert from 'node:assert/strict'; +import { replaceInFile } from '../../utils/fs'; import { ng } from '../../utils/process'; import { updateJsonFile } from '../../utils/project'; +import { executeBrowserTest } from '../../utils/puppeteer'; export default async function () { // Add lazy route. @@ -19,29 +21,6 @@ export default async function () { `routes: Routes = [{path: 'lazy', loadComponent: () => import('./lazy/lazy').then(c => c.Lazy)}];`, ); - // Add lazy route e2e - await writeFile( - 'e2e/src/app.e2e-spec.ts', - ` - import { browser, logging, element, by } from 'protractor'; - - describe('workspace-project App', () => { - it('should display lazy route', async () => { - await browser.get(browser.baseUrl + '/lazy'); - expect(await element(by.css('app-lazy p')).getText()).toEqual('lazy works!'); - }); - - afterEach(async () => { - // Assert that there are no errors emitted from the browser - const logs = await browser.manage().logs().get(logging.Type.BROWSER); - expect(logs).not.toContain(jasmine.objectContaining({ - level: logging.Level.SEVERE, - })); - }); - }); - `, - ); - const testCases = [ { aot: false, @@ -64,7 +43,16 @@ export default async function () { }); try { - await ng('e2e'); + await executeBrowserTest({ + checkFn: async (page) => { + const baseUrl = page.url(); + await page.goto(new URL('/lazy', baseUrl).href); + + await page.waitForSelector('app-lazy p'); + const lazyText = await page.$eval('app-lazy p', (el) => el.textContent); + assert.strictEqual(lazyText, 'lazy works!'); + }, + }); } catch (error) { console.error(`Test case AOT ${aot} with CSP header ${csp} failed.`); throw error;