diff --git a/src/server/supplements/inspectorController.ts b/src/server/supplements/inspectorController.ts
index 8d8f8bdc9ca07..aa65e89a19008 100644
--- a/src/server/supplements/inspectorController.ts
+++ b/src/server/supplements/inspectorController.ts
@@ -75,6 +75,7 @@ export class InspectorController implements InstrumentationListener {
case 'after':
const originalMetadata = this._waitOperations.get(info.waitId)!;
originalMetadata.endTime = metadata.endTime;
+ originalMetadata.error = info.error;
this._waitOperations.delete(info.waitId);
metadata = originalMetadata;
break;
diff --git a/src/server/supplements/recorderSupplement.ts b/src/server/supplements/recorderSupplement.ts
index a39ef97282486..3de8ae642f6e8 100644
--- a/src/server/supplements/recorderSupplement.ts
+++ b/src/server/supplements/recorderSupplement.ts
@@ -447,8 +447,10 @@ export class RecorderSupplement {
selector: metadata.params?.selector,
};
let duration = metadata.endTime ? metadata.endTime - metadata.startTime : undefined;
- if (duration && metadata.pauseStartTime && metadata.pauseEndTime)
+ if (typeof duration === 'number' && metadata.pauseStartTime && metadata.pauseEndTime) {
duration -= (metadata.pauseEndTime - metadata.pauseStartTime);
+ duration = Math.max(duration, 0);
+ }
logs.push({
id: metadata.id,
messages: metadata.log,
diff --git a/test/pause.spec.ts b/test/pause.spec.ts
index d9140b327e8f5..841e9bd814645 100644
--- a/test/pause.spec.ts
+++ b/test/pause.spec.ts
@@ -163,6 +163,23 @@ describe('pause', (suite, { mode }) => {
await scriptPromise;
});
+ it('should highlight waitForEvent', async ({page, recorderPageGetter}) => {
+ await page.setContent('');
+ const scriptPromise = (async () => {
+ await page.pause();
+ await Promise.all([
+ page.waitForEvent('console'),
+ page.click('button'),
+ ]);
+ })();
+ const recorderPage = await recorderPageGetter();
+ await recorderPage.click('[title="Step over"]');
+ await recorderPage.waitForSelector('.source-line-paused:has-text("page.click")');
+ await recorderPage.waitForSelector('.source-line-running:has-text("page.waitForEvent")');
+ await recorderPage.click('[title="Resume"]');
+ await scriptPromise;
+ });
+
it('should populate log with waitForEvent', async ({page, recorderPageGetter}) => {
await page.setContent('');
const scriptPromise = (async () => {
@@ -178,7 +195,7 @@ describe('pause', (suite, { mode }) => {
await recorderPage.waitForSelector('.source-line-paused:has-text("page.pause(); // 2")');
expect(await sanitizeLog(recorderPage)).toEqual([
'page.pause- XXms',
- 'page.waitForEvent(console)- XXms',
+ 'page.waitForEvent(console)',
'page.click(button)- XXms',
'page.pause',
]);
@@ -200,12 +217,36 @@ describe('pause', (suite, { mode }) => {
'page.isChecked(button)- XXms',
'checking \"checked\" state of \"button\"',
'selector resolved to ',
- 'Not a checkbox or radio button',
+ 'error: Not a checkbox or radio button',
]);
const error = await scriptPromise;
expect(error.message).toContain('Not a checkbox or radio button');
});
+ it('should populate log with error in waitForEvent', async ({page, recorderPageGetter}) => {
+ await page.setContent('');
+ const scriptPromise = (async () => {
+ await page.pause();
+ await Promise.all([
+ page.waitForEvent('console', { timeout: 1 }),
+ page.click('button'),
+ ]);
+ })().catch(() => {});
+ const recorderPage = await recorderPageGetter();
+ await recorderPage.click('[title="Step over"]');
+ await recorderPage.waitForSelector('.source-line-paused:has-text("page.click")');
+ await recorderPage.waitForSelector('.source-line-error:has-text("page.waitForEvent")');
+ await recorderPage.click('[title="Resume"]');
+ expect(await sanitizeLog(recorderPage)).toEqual([
+ 'page.pause- XXms',
+ 'page.waitForEvent(console)',
+ 'waiting for event \"console\"',
+ 'error: Timeout while waiting for event \"console\"',
+ 'page.click(button)- XXms',
+ ]);
+ await scriptPromise;
+ });
+
it('should pause on page close', async ({ page, recorderPageGetter }) => {
const scriptPromise = (async () => {
await page.pause();
@@ -234,13 +275,11 @@ describe('pause', (suite, { mode }) => {
async function sanitizeLog(recorderPage: Page): Promise {
const results = [];
for (const entry of await recorderPage.$$('.call-log-call')) {
- const header = await (await (await entry.$('.call-log-call-header')).textContent()).replace(/— \d+(\.\d+)?(ms|s)/, '- XXms');
- results.push(header);
- results.push(...await entry.$$eval('.call-log-message', ee => ee.map(e => e.textContent)));
- const errorElement = await entry.$('.call-log-error');
- const error = errorElement ? await errorElement.textContent() : undefined;
- if (error)
- results.push(error);
+ const header = (await (await entry.$('.call-log-call-header')).textContent()).replace(/— [\d.]+(ms|s)/, '- XXms');
+ results.push(header.replace(/page\.waitForEvent\(console\).*/, 'page.waitForEvent(console)'));
+ results.push(...await entry.$$eval('.call-log-message', ee => ee.map(e => {
+ return (e.classList.contains('error') ? 'error: ' : '') + e.textContent;
+ })));
}
return results;
}