2022-04-06 02:10:12 +03:00
|
|
|
/**
|
|
|
|
* Copyright (c) Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2023-03-21 17:40:54 +03:00
|
|
|
import type { Fixtures, FrameLocator, Locator, Page, Browser, BrowserContext } from '@playwright/test';
|
2023-03-30 06:43:08 +03:00
|
|
|
import { step } from './baseTest';
|
2023-06-06 02:30:30 +03:00
|
|
|
import { openTraceViewerApp } from '../../packages/playwright-core/lib/server';
|
2022-04-06 02:10:12 +03:00
|
|
|
|
|
|
|
type BaseTestFixtures = {
|
|
|
|
context: BrowserContext;
|
|
|
|
};
|
|
|
|
|
|
|
|
type BaseWorkerFixtures = {
|
|
|
|
headless: boolean;
|
|
|
|
browser: Browser;
|
|
|
|
browserName: 'chromium' | 'firefox' | 'webkit';
|
|
|
|
playwright: typeof import('@playwright/test');
|
|
|
|
};
|
|
|
|
|
|
|
|
export type TraceViewerFixtures = {
|
2023-01-28 01:20:25 +03:00
|
|
|
showTraceViewer: (trace: string[], options?: {host?: string, port?: number}) => Promise<TraceViewerPage>;
|
2022-04-06 02:10:12 +03:00
|
|
|
runAndTrace: (body: () => Promise<void>) => Promise<TraceViewerPage>;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TraceViewerPage {
|
|
|
|
actionTitles: Locator;
|
|
|
|
callLines: Locator;
|
|
|
|
consoleLines: Locator;
|
2023-09-02 06:12:05 +03:00
|
|
|
logLines: Locator;
|
2022-04-06 02:10:12 +03:00
|
|
|
consoleLineMessages: Locator;
|
|
|
|
consoleStacks: Locator;
|
|
|
|
stackFrames: Locator;
|
|
|
|
networkRequests: Locator;
|
|
|
|
snapshotContainer: Locator;
|
|
|
|
|
|
|
|
constructor(public page: Page) {
|
|
|
|
this.actionTitles = page.locator('.action-title');
|
2023-03-07 23:43:16 +03:00
|
|
|
this.callLines = page.locator('.call-tab .call-line');
|
2023-09-02 06:12:05 +03:00
|
|
|
this.logLines = page.getByTestId('log-list').locator('.list-view-entry');
|
2022-04-06 02:10:12 +03:00
|
|
|
this.consoleLines = page.locator('.console-line');
|
|
|
|
this.consoleLineMessages = page.locator('.console-line-message');
|
|
|
|
this.consoleStacks = page.locator('.console-stack');
|
2023-02-25 02:31:10 +03:00
|
|
|
this.stackFrames = page.getByTestId('stack-trace').locator('.list-view-entry');
|
2023-08-30 08:20:28 +03:00
|
|
|
this.networkRequests = page.getByTestId('network-request-list').locator('.list-view-entry');
|
2023-03-21 17:40:54 +03:00
|
|
|
this.snapshotContainer = page.locator('.snapshot-container iframe.snapshot-visible[name=snapshot]');
|
2022-04-06 02:10:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async actionIconsText(action: string) {
|
2023-02-16 18:59:21 +03:00
|
|
|
const entry = await this.page.waitForSelector(`.list-view-entry:has-text("${action}")`);
|
2022-04-06 02:10:12 +03:00
|
|
|
await entry.waitForSelector('.action-icon-value:visible');
|
|
|
|
return await entry.$$eval('.action-icon-value:visible', ee => ee.map(e => e.textContent));
|
|
|
|
}
|
|
|
|
|
|
|
|
async actionIcons(action: string) {
|
2023-02-16 18:59:21 +03:00
|
|
|
return await this.page.waitForSelector(`.list-view-entry:has-text("${action}") .action-icons`);
|
2022-04-06 02:10:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async selectAction(title: string, ordinal: number = 0) {
|
|
|
|
await this.page.locator(`.action-title:has-text("${title}")`).nth(ordinal).click();
|
|
|
|
}
|
|
|
|
|
|
|
|
async selectSnapshot(name: string) {
|
2023-02-17 22:19:53 +03:00
|
|
|
await this.page.click(`.snapshot-tab .tabbed-pane-tab-label:has-text("${name}")`);
|
2022-04-06 02:10:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async showConsoleTab() {
|
|
|
|
await this.page.click('text="Console"');
|
|
|
|
}
|
|
|
|
|
|
|
|
async showSourceTab() {
|
|
|
|
await this.page.click('text="Source"');
|
|
|
|
}
|
|
|
|
|
|
|
|
async showNetworkTab() {
|
|
|
|
await this.page.click('text="Network"');
|
|
|
|
}
|
|
|
|
|
2023-03-30 06:43:08 +03:00
|
|
|
@step
|
2023-03-21 17:40:54 +03:00
|
|
|
async snapshotFrame(actionName: string, ordinal: number = 0, hasSubframe: boolean = false): Promise<FrameLocator> {
|
|
|
|
await this.selectAction(actionName, ordinal);
|
|
|
|
while (this.page.frames().length < (hasSubframe ? 4 : 3))
|
2022-04-06 02:10:12 +03:00
|
|
|
await this.page.waitForEvent('frameattached');
|
2023-03-21 17:40:54 +03:00
|
|
|
return this.page.frameLocator('iframe.snapshot-visible[name=snapshot]');
|
2022-04-06 02:10:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const traceViewerFixtures: Fixtures<TraceViewerFixtures, {}, BaseTestFixtures, BaseWorkerFixtures> = {
|
2023-08-05 00:59:48 +03:00
|
|
|
showTraceViewer: async ({ playwright, browserName, headless }, use, testInfo) => {
|
2022-09-27 22:45:42 +03:00
|
|
|
const browsers: Browser[] = [];
|
|
|
|
const contextImpls: any[] = [];
|
2023-01-28 01:20:25 +03:00
|
|
|
await use(async (traces: string[], { host, port } = {}) => {
|
2023-06-06 02:30:30 +03:00
|
|
|
const pageImpl = await openTraceViewerApp(traces, browserName, { headless, host, port });
|
2023-03-02 02:27:23 +03:00
|
|
|
const contextImpl = pageImpl.context();
|
2022-09-27 22:45:42 +03:00
|
|
|
const browser = await playwright.chromium.connectOverCDP(contextImpl._browser.options.wsEndpoint);
|
|
|
|
browsers.push(browser);
|
|
|
|
contextImpls.push(contextImpl);
|
2022-04-06 02:10:12 +03:00
|
|
|
return new TraceViewerPage(browser.contexts()[0].pages()[0]);
|
|
|
|
});
|
2022-09-27 22:45:42 +03:00
|
|
|
for (const browser of browsers)
|
|
|
|
await browser.close();
|
|
|
|
for (const contextImpl of contextImpls)
|
|
|
|
await contextImpl._browser.close();
|
2022-04-06 02:10:12 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
runAndTrace: async ({ context, showTraceViewer }, use, testInfo) => {
|
|
|
|
await use(async (body: () => Promise<void>) => {
|
|
|
|
const traceFile = testInfo.outputPath('trace.zip');
|
|
|
|
await context.tracing.start({ snapshots: true, screenshots: true, sources: true });
|
|
|
|
await body();
|
|
|
|
await context.tracing.stop({ path: traceFile });
|
|
|
|
return showTraceViewer([traceFile]);
|
|
|
|
});
|
|
|
|
},
|
2023-01-28 01:20:25 +03:00
|
|
|
};
|