| 
									
										
										
										
											2021-04-30 07:40:22 -07: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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-09 17:21:17 -08:00
										 |  |  | import fs from 'fs'; | 
					
						
							| 
									
										
										
										
											2022-04-18 19:20:49 -08:00
										 |  |  | import { jpegjs } from 'playwright-core/lib/utilsBundle'; | 
					
						
							| 
									
										
										
										
											2021-10-25 10:49:59 -08:00
										 |  |  | import path from 'path'; | 
					
						
							| 
									
										
										
										
											2022-03-25 15:05:50 -08:00
										 |  |  | import { browserTest, contextTest as test, expect } from '../config/browserTest'; | 
					
						
							|  |  |  | import { parseTrace } from '../config/utils'; | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-26 12:45:53 -08:00
										 |  |  | test.skip(({ trace }) => trace === 'on'); | 
					
						
							| 
									
										
										
										
											2021-08-19 19:09:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-19 10:06:31 -06:00
										 |  |  | // https://github.com/microsoft/playwright/issues/14285
 | 
					
						
							|  |  |  | test.fixme(({ browserName, headless }) => browserName === 'firefox' && !headless); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-03 13:05:58 -07:00
										 |  |  | test('should collect trace with resources, but no js', async ({ context, page, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-07-14 18:43:51 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-08-03 13:05:58 -07:00
										 |  |  |   await page.goto(server.PREFIX + '/frames/frame.html'); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							| 
									
										
										
										
											2021-09-07 13:48:30 -07:00
										 |  |  |   await page.mouse.move(20, 20); | 
					
						
							|  |  |  |   await page.mouse.dblclick(30, 30); | 
					
						
							|  |  |  |   await page.keyboard.insertText('abc'); | 
					
						
							| 
									
										
										
										
											2021-06-14 16:01:18 -07:00
										 |  |  |   await page.waitForTimeout(2000);  // Give it some time to produce screenshots.
 | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   await page.close(); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							| 
									
										
										
										
											2021-05-13 22:36:34 -07:00
										 |  |  |   expect(events[0].type).toBe('context-options'); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |   expect(eventsToActions(events)).toEqual([ | 
					
						
							|  |  |  |     'page.goto', | 
					
						
							|  |  |  |     'page.setContent', | 
					
						
							|  |  |  |     'page.click', | 
					
						
							|  |  |  |     'mouse.move', | 
					
						
							|  |  |  |     'mouse.dblclick', | 
					
						
							|  |  |  |     'keyboard.insertText', | 
					
						
							|  |  |  |     'page.waitForTimeout', | 
					
						
							|  |  |  |     'page.close', | 
					
						
							|  |  |  |     'tracing.stop', | 
					
						
							|  |  |  |   ]); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   expect(events.some(e => e.type === 'frame-snapshot')).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-05-08 11:35:36 -07:00
										 |  |  |   expect(events.some(e => e.type === 'screencast-frame')).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-09-07 15:23:13 -07:00
										 |  |  |   const style = events.find(e => e.type === 'resource-snapshot' && e.snapshot.request.url.endsWith('style.css')); | 
					
						
							|  |  |  |   expect(style).toBeTruthy(); | 
					
						
							|  |  |  |   expect(style.snapshot.response.content._sha1).toBeTruthy(); | 
					
						
							|  |  |  |   const script = events.find(e => e.type === 'resource-snapshot' && e.snapshot.request.url.endsWith('script.js')); | 
					
						
							|  |  |  |   expect(script).toBeTruthy(); | 
					
						
							|  |  |  |   expect(script.snapshot.response.content._sha1).toBe(undefined); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  | test('should use the correct apiName for event driven callbacks', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start(); | 
					
						
							|  |  |  |   await page.route('**/empty.html', route => route.continue()); | 
					
						
							|  |  |  |   // page.goto -> page.route should be included in the trace since its handled.
 | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/empty.html'); | 
					
						
							|  |  |  |   // page.route -> internalContinue should not be included in the trace since it was handled by Playwright internally.
 | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/grid.html'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // The default internal dialog handler should not provide an action.
 | 
					
						
							|  |  |  |   await page.evaluate(() => alert('yo')); | 
					
						
							|  |  |  |   await page.reload(); | 
					
						
							|  |  |  |   // now we do it again with a dialog event listener attached which should produce an action.
 | 
					
						
							|  |  |  |   page.on('dialog', dialog => { | 
					
						
							|  |  |  |     dialog.accept('answer!'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.evaluate(() => alert('yo')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   expect(events[0].type).toBe('context-options'); | 
					
						
							|  |  |  |   expect(eventsToActions(events)).toEqual([ | 
					
						
							|  |  |  |     'page.route', | 
					
						
							|  |  |  |     'page.goto', | 
					
						
							|  |  |  |     'route.continue', | 
					
						
							|  |  |  |     'page.goto', | 
					
						
							|  |  |  |     'page.evaluate', | 
					
						
							|  |  |  |     'page.reload', | 
					
						
							|  |  |  |     'page.evaluate', | 
					
						
							|  |  |  |     'dialog.accept', | 
					
						
							|  |  |  |     'tracing.stop', | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 14:52:16 -07:00
										 |  |  | test('should not collect snapshots by default', async ({ context, page, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.start(); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							|  |  |  |   await page.close(); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   expect(events.some(e => e.type === 'frame-snapshot')).toBeFalsy(); | 
					
						
							|  |  |  |   expect(events.some(e => e.type === 'resource-snapshot')).toBeFalsy(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-20 10:19:42 -07:00
										 |  |  | test('should not include buffers in the trace', async ({ context, page, server, mode }, testInfo) => { | 
					
						
							|  |  |  |   test.skip(mode !== 'default', 'no buffers with remote connections'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-17 16:17:25 -07:00
										 |  |  |   await context.tracing.start({ snapshots: true }); | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/empty.html'); | 
					
						
							|  |  |  |   await page.screenshot(); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   const screenshotEvent = events.find(e => e.type === 'action' && e.metadata.apiName === 'page.screenshot'); | 
					
						
							|  |  |  |   expect(screenshotEvent.metadata.snapshots.length).toBe(2); | 
					
						
							|  |  |  |   expect(screenshotEvent.metadata.result).toEqual({}); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-29 01:20:49 +00:00
										 |  |  | test('should exclude internal pages', async ({ browserName, context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   test.fixme(true, 'https://github.com/microsoft/playwright/issues/6743'); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.start(); | 
					
						
							| 
									
										
										
										
											2021-05-29 01:20:49 +00:00
										 |  |  |   await context.storageState(); | 
					
						
							|  |  |  |   await page.close(); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							| 
									
										
										
										
											2021-05-29 01:20:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   const pageIds = new Set(); | 
					
						
							|  |  |  |   trace.events.forEach(e => { | 
					
						
							|  |  |  |     const pageId = e.metadata?.pageId; | 
					
						
							|  |  |  |     if (pageId) | 
					
						
							|  |  |  |       pageIds.add(pageId); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   expect(pageIds.size).toBe(1); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-02 15:53:47 -08:00
										 |  |  | test('should include context API requests', async ({ browserName, context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ snapshots: true }); | 
					
						
							|  |  |  |   await page.request.post(server.PREFIX + '/simple.json', { data: { foo: 'bar' } }); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   const postEvent = events.find(e => e.metadata?.apiName === 'apiRequestContext.post'); | 
					
						
							|  |  |  |   expect(postEvent).toBeTruthy(); | 
					
						
							|  |  |  |   const harEntry = events.find(e => e.type === 'resource-snapshot'); | 
					
						
							|  |  |  |   expect(harEntry).toBeTruthy(); | 
					
						
							|  |  |  |   expect(harEntry.snapshot.request.url).toBe(server.PREFIX + '/simple.json'); | 
					
						
							|  |  |  |   expect(harEntry.snapshot.response.status).toBe(200); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | test('should collect two traces', async ({ context, page, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace1.zip') }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   await page.dblclick('"Click"'); | 
					
						
							|  |  |  |   await page.close(); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace2.zip') }); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { events } = await parseTrace(testInfo.outputPath('trace1.zip')); | 
					
						
							| 
									
										
										
										
											2021-05-13 22:36:34 -07:00
										 |  |  |     expect(events[0].type).toBe('context-options'); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |     expect(eventsToActions(events)).toEqual([ | 
					
						
							|  |  |  |       'page.goto', | 
					
						
							|  |  |  |       'page.setContent', | 
					
						
							|  |  |  |       'page.click', | 
					
						
							|  |  |  |       'tracing.stop', | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { events } = await parseTrace(testInfo.outputPath('trace2.zip')); | 
					
						
							| 
									
										
										
										
											2021-05-13 22:36:34 -07:00
										 |  |  |     expect(events[0].type).toBe('context-options'); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |     expect(eventsToActions(events)).toEqual([ | 
					
						
							|  |  |  |       'page.dblclick', | 
					
						
							|  |  |  |       'page.close', | 
					
						
							|  |  |  |       'tracing.stop', | 
					
						
							|  |  |  |     ]); | 
					
						
							| 
									
										
										
										
											2021-04-30 07:40:22 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-15 17:40:34 -08:00
										 |  |  | test('should not include trace resources from the provious chunks', async ({ context, page, server, browserName }, testInfo) => { | 
					
						
							|  |  |  |   test.skip(browserName !== 'chromium', 'The number of screenshots is flaky in non-Chromium'); | 
					
						
							| 
									
										
										
										
											2021-12-10 14:07:22 -08:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true, sources: true }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await context.tracing.startChunk(); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							| 
									
										
										
										
											2021-12-13 14:37:44 -08:00
										 |  |  |   // Give it enough time for both screenshots to get into the trace.
 | 
					
						
							| 
									
										
										
										
											2022-11-07 15:35:21 -08:00
										 |  |  |   await new Promise(f => setTimeout(f, 3000)); | 
					
						
							| 
									
										
										
										
											2021-12-10 14:07:22 -08:00
										 |  |  |   await context.tracing.stopChunk({ path: testInfo.outputPath('trace1.zip') }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await context.tracing.startChunk(); | 
					
						
							|  |  |  |   await context.tracing.stopChunk({ path: testInfo.outputPath('trace2.zip') }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { resources } = await parseTrace(testInfo.outputPath('trace1.zip')); | 
					
						
							|  |  |  |     const names = Array.from(resources.keys()); | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.html')).length).toBe(1); | 
					
						
							| 
									
										
										
										
											2021-12-15 10:40:18 -08:00
										 |  |  |     expect(names.filter(n => n.endsWith('.jpeg')).length).toBeGreaterThan(0); | 
					
						
							| 
									
										
										
										
											2021-12-10 14:07:22 -08:00
										 |  |  |     // 1 source file for the test.
 | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.txt')).length).toBe(1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { resources } = await parseTrace(testInfo.outputPath('trace2.zip')); | 
					
						
							|  |  |  |     const names = Array.from(resources.keys()); | 
					
						
							|  |  |  |     // 1 network resource should be preserved.
 | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.html')).length).toBe(1); | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.jpeg')).length).toBe(0); | 
					
						
							|  |  |  |     // 1 source file for the test.
 | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.txt')).length).toBe(1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should overwrite existing file', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true, sources: true }); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							|  |  |  |   const path = testInfo.outputPath('trace1.zip'); | 
					
						
							|  |  |  |   await context.tracing.stop({ path }); | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { resources } = await parseTrace(path); | 
					
						
							|  |  |  |     const names = Array.from(resources.keys()); | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.html')).length).toBe(1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true, sources: true }); | 
					
						
							|  |  |  |   await context.tracing.stop({ path }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const { resources } = await parseTrace(path); | 
					
						
							|  |  |  |     const names = Array.from(resources.keys()); | 
					
						
							|  |  |  |     expect(names.filter(n => n.endsWith('.html')).length).toBe(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-09 17:21:17 -08:00
										 |  |  | test('should collect sources', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ sources: true }); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace1.zip') }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { resources } = await parseTrace(testInfo.outputPath('trace1.zip')); | 
					
						
							|  |  |  |   const sourceNames = Array.from(resources.keys()).filter(k => k.endsWith('.txt')); | 
					
						
							|  |  |  |   expect(sourceNames.length).toBe(1); | 
					
						
							|  |  |  |   const sourceFile = resources.get(sourceNames[0]); | 
					
						
							|  |  |  |   const thisFile = await fs.promises.readFile(__filename); | 
					
						
							|  |  |  |   expect(sourceFile).toEqual(thisFile); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-07 11:22:01 -08:00
										 |  |  | test('should record network failures', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ snapshots: true }); | 
					
						
							|  |  |  |   await page.route('**/*', route => route.abort('connectionaborted')); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE).catch(e => {}); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace1.zip') }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace1.zip')); | 
					
						
							|  |  |  |   const requestEvent = events.find(e => e.type === 'resource-snapshot' && !!e.snapshot.response._failureText); | 
					
						
							|  |  |  |   expect(requestEvent).toBeTruthy(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-10 22:24:04 -07:00
										 |  |  | test('should not stall on dialogs', async ({ page, context, server }) => { | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   page.on('dialog', async dialog => { | 
					
						
							|  |  |  |     await dialog.accept(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							|  |  |  |     confirm('are you sure'); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await context.tracing.stop(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  | for (const params of [ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     id: 'fit', | 
					
						
							|  |  |  |     width: 500, | 
					
						
							|  |  |  |     height: 500, | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     id: 'crop', | 
					
						
							|  |  |  |     width: 400, // Less than 450 to test firefox
 | 
					
						
							|  |  |  |     height: 800, | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |   }, | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     id: 'scale', | 
					
						
							|  |  |  |     width: 1024, | 
					
						
							|  |  |  |     height: 768, | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |   } | 
					
						
							|  |  |  | ]) { | 
					
						
							| 
									
										
										
										
											2021-06-03 14:33:33 -07:00
										 |  |  |   browserTest(`should produce screencast frames ${params.id}`, async ({ video, contextFactory, browserName, platform, headless }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-10-26 12:45:53 -08:00
										 |  |  |     browserTest.fixme(browserName === 'chromium' && video === 'on', 'Same screencast resolution conflicts'); | 
					
						
							| 
									
										
										
										
											2021-06-03 14:33:33 -07:00
										 |  |  |     browserTest.fixme(browserName === 'chromium' && !headless, 'Chromium screencast on headed has a min width issue'); | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |     browserTest.fixme(params.id === 'fit' && browserName === 'chromium' && platform === 'darwin', 'High DPI maxes image at 600x600'); | 
					
						
							| 
									
										
										
										
											2021-05-17 19:06:18 +00:00
										 |  |  |     browserTest.fixme(params.id === 'fit' && browserName === 'webkit' && platform === 'linux', 'Image size is flaky'); | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     const scale = Math.min(800 / params.width, 600 / params.height, 1); | 
					
						
							|  |  |  |     const previewWidth = params.width * scale; | 
					
						
							|  |  |  |     const previewHeight = params.height * scale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-27 18:58:08 +02:00
										 |  |  |     const context = await contextFactory({ viewport: { width: params.width, height: params.height } }); | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |     await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     const page = await context.newPage(); | 
					
						
							|  |  |  |     // Make sure we have a chance to paint.
 | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |     for (let i = 0; i < 10; ++i) { | 
					
						
							|  |  |  |       await page.setContent('<body style="box-sizing: border-box; width: 100%; height: 100%; margin:0; background: red; border: 50px solid blue"></body>'); | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |       await page.evaluate(() => new Promise(requestAnimationFrame)); | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-06-02 10:04:25 -07:00
										 |  |  |     await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const { events, resources } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |     const frames = events.filter(e => e.type === 'screencast-frame'); | 
					
						
							| 
									
										
										
										
											2021-05-12 08:35:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Check all frame sizes.
 | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     for (const frame of frames) { | 
					
						
							|  |  |  |       expect(frame.width).toBe(params.width); | 
					
						
							|  |  |  |       expect(frame.height).toBe(params.height); | 
					
						
							|  |  |  |       const buffer = resources.get('resources/' + frame.sha1); | 
					
						
							| 
									
										
										
										
											2022-04-18 19:20:49 -08:00
										 |  |  |       const image = jpegjs.decode(buffer); | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |       expect(image.width).toBe(previewWidth); | 
					
						
							|  |  |  |       expect(image.height).toBe(previewHeight); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const frame = frames[frames.length - 1]; // pick last frame.
 | 
					
						
							|  |  |  |     const buffer = resources.get('resources/' + frame.sha1); | 
					
						
							| 
									
										
										
										
											2022-04-18 19:20:49 -08:00
										 |  |  |     const image = jpegjs.decode(buffer); | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  |     expect(image.data.byteLength).toBe(previewWidth * previewHeight * 4); | 
					
						
							|  |  |  |     expectRed(image.data, previewWidth * previewHeight * 4 / 2 + previewWidth * 4 / 2); // center is red
 | 
					
						
							|  |  |  |     expectBlue(image.data, previewWidth * 5 * 4 + previewWidth * 4 / 2); // top
 | 
					
						
							|  |  |  |     expectBlue(image.data, previewWidth * (previewHeight - 5) * 4 + previewWidth * 4 / 2); // bottom
 | 
					
						
							|  |  |  |     expectBlue(image.data, previewWidth * previewHeight * 4 / 2 + 5 * 4); // left
 | 
					
						
							|  |  |  |     expectBlue(image.data, previewWidth * previewHeight * 4 / 2 + (previewWidth - 5) * 4); // right
 | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-25 17:14:19 -07:00
										 |  |  | test('should include interrupted actions', async ({ context, page, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-07-14 18:43:51 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-06-25 17:14:19 -07:00
										 |  |  |   await page.goto(server.EMPTY_PAGE); | 
					
						
							|  |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   page.click('"ClickNoButton"').catch(() =>  {}); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							|  |  |  |   await context.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { events } = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   const clickEvent = events.find(e => e.metadata?.apiName === 'page.click'); | 
					
						
							|  |  |  |   expect(clickEvent).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-07-02 14:33:38 -07:00
										 |  |  |   expect(clickEvent.metadata.error.error.message).toBe('Action was interrupted'); | 
					
						
							| 
									
										
										
										
											2021-06-25 17:14:19 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  | test('should throw when starting with different options', async ({ context }) => { | 
					
						
							| 
									
										
										
										
											2021-08-03 16:08:06 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   const error = await context.tracing.start({ screenshots: false, snapshots: false }).catch(e => e); | 
					
						
							|  |  |  |   expect(error.message).toContain('Tracing has been already started with different options'); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-08-03 16:08:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  | test('should throw when stopping without start', async ({ context }, testInfo) => { | 
					
						
							|  |  |  |   const error = await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }).catch(e => e); | 
					
						
							|  |  |  |   expect(error.message).toContain('Must start tracing before stopping'); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-08-03 16:08:06 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  | test('should not throw when stopping without start but not exporting', async ({ context }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.stop(); | 
					
						
							| 
									
										
										
										
											2021-08-03 16:08:06 -07:00
										 |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  | test('should work with multiple chunks', async ({ context, page, server }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/frames/frame.html'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   await context.tracing.startChunk(); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   await page.setContent('<button>Click</button>'); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							|  |  |  |   page.click('"ClickNoButton"').catch(() =>  {}); | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   await context.tracing.stopChunk({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   await context.tracing.startChunk(); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   await page.hover('"Click"'); | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   await context.tracing.stopChunk({ path: testInfo.outputPath('trace2.zip') }); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-18 21:05:59 -07:00
										 |  |  |   await context.tracing.startChunk(); | 
					
						
							|  |  |  |   await page.click('"Click"'); | 
					
						
							|  |  |  |   await context.tracing.stopChunk();  // Should stop without a path.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   const trace1 = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							|  |  |  |   expect(trace1.events[0].type).toBe('context-options'); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |   expect(eventsToActions(trace1.events)).toEqual([ | 
					
						
							|  |  |  |     'page.setContent', | 
					
						
							|  |  |  |     'page.click', | 
					
						
							|  |  |  |     'page.click', | 
					
						
							|  |  |  |     'tracing.stopChunk', | 
					
						
							|  |  |  |   ]); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   expect(trace1.events.find(e => e.metadata?.apiName === 'page.click' && !!e.metadata.error)).toBeTruthy(); | 
					
						
							|  |  |  |   expect(trace1.events.find(e => e.metadata?.apiName === 'page.click' && e.metadata?.error?.error?.message === 'Action was interrupted')).toBeTruthy(); | 
					
						
							|  |  |  |   expect(trace1.events.some(e => e.type === 'frame-snapshot')).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-08-24 13:17:58 -07:00
										 |  |  |   expect(trace1.events.some(e => e.type === 'resource-snapshot' && e.snapshot.request.url.endsWith('style.css'))).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const trace2 = await parseTrace(testInfo.outputPath('trace2.zip')); | 
					
						
							|  |  |  |   expect(trace2.events[0].type).toBe('context-options'); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |   expect(eventsToActions(trace2.events)).toEqual([ | 
					
						
							|  |  |  |     'page.hover', | 
					
						
							|  |  |  |     'tracing.stopChunk', | 
					
						
							|  |  |  |   ]); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  |   expect(trace2.events.some(e => e.type === 'frame-snapshot')).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-08-31 17:03:31 -07:00
										 |  |  |   expect(trace2.events.some(e => e.type === 'resource-snapshot' && e.snapshot.request.url.endsWith('style.css'))).toBeTruthy(); | 
					
						
							| 
									
										
										
										
											2021-08-04 21:11:35 -07:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-06-25 17:14:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-19 07:26:24 -07:00
										 |  |  | test('should export trace concurrently to second navigation', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   for (let timeout = 0; timeout < 200; timeout += 20) { | 
					
						
							|  |  |  |     await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |     await page.goto(server.PREFIX + '/grid.html'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Navigate to the same page to produce the same trace resources
 | 
					
						
							|  |  |  |     // that might be concurrently exported.
 | 
					
						
							|  |  |  |     const promise = page.goto(server.PREFIX + '/grid.html'); | 
					
						
							|  |  |  |     await page.waitForTimeout(timeout); | 
					
						
							|  |  |  |     await Promise.all([ | 
					
						
							|  |  |  |       promise, | 
					
						
							|  |  |  |       context.tracing.stop({ path: testInfo.outputPath('trace.zip') }), | 
					
						
							|  |  |  |     ]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-19 18:20:15 -07:00
										 |  |  | test('should not hang for clicks that open dialogs', async ({ context, page }) => { | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   const dialogPromise = page.waitForEvent('dialog'); | 
					
						
							|  |  |  |   await page.setContent(`<div onclick='window.alert(123)'>Click me</div>`); | 
					
						
							|  |  |  |   await page.click('div', { timeout: 2000 }).catch(() => {}); | 
					
						
							|  |  |  |   const dialog = await dialogPromise; | 
					
						
							|  |  |  |   await dialog.dismiss(); | 
					
						
							|  |  |  |   await context.tracing.stop(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-16 09:09:15 -08:00
										 |  |  | test('should ignore iframes in head', async ({ context, page, server }, testInfo) => { | 
					
						
							|  |  |  |   await page.goto(server.PREFIX + '/input/button.html'); | 
					
						
							|  |  |  |   await page.evaluate(() => { | 
					
						
							|  |  |  |     document.head.appendChild(document.createElement('iframe')); | 
					
						
							|  |  |  |     // Add iframe in a shadow tree.
 | 
					
						
							|  |  |  |     const div = document.createElement('div'); | 
					
						
							|  |  |  |     document.head.appendChild(div); | 
					
						
							|  |  |  |     const shadow = div.attachShadow({ mode: 'open' }); | 
					
						
							|  |  |  |     shadow.appendChild(document.createElement('iframe')); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   await page.click('button'); | 
					
						
							|  |  |  |   await context.tracing.stopChunk({ path: testInfo.outputPath('trace.zip') }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(testInfo.outputPath('trace.zip')); | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  |   expect(eventsToActions(trace.events)).toEqual([ | 
					
						
							|  |  |  |     'page.click', | 
					
						
							|  |  |  |     'tracing.stopChunk', | 
					
						
							|  |  |  |   ]); | 
					
						
							| 
									
										
										
										
											2022-02-16 09:09:15 -08:00
										 |  |  |   expect(trace.events.find(e => e.type === 'frame-snapshot')).toBeTruthy(); | 
					
						
							|  |  |  |   expect(trace.events.find(e => e.type === 'frame-snapshot' && JSON.stringify(e.snapshot.html).includes('IFRAME'))).toBeFalsy(); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-25 10:49:59 -08:00
										 |  |  | test('should hide internal stack frames', async ({ context, page }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   let evalPromise; | 
					
						
							|  |  |  |   page.on('dialog', dialog => { | 
					
						
							|  |  |  |     evalPromise = page.evaluate('2+2'); | 
					
						
							|  |  |  |     dialog.dismiss(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.setContent(`<div onclick='window.alert(123)'>Click me</div>`); | 
					
						
							|  |  |  |   await page.click('div'); | 
					
						
							|  |  |  |   await evalPromise; | 
					
						
							|  |  |  |   const tracePath = testInfo.outputPath('trace.zip'); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: tracePath }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(tracePath); | 
					
						
							|  |  |  |   const actions = trace.events.filter(e => e.type === 'action' && !e.metadata.apiName.startsWith('tracing.')); | 
					
						
							|  |  |  |   expect(actions).toHaveLength(4); | 
					
						
							|  |  |  |   for (const action of actions) | 
					
						
							|  |  |  |     expect(relativeStack(action)).toEqual(['tracing.spec.ts']); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | test('should hide internal stack frames in expect', async ({ context, page }, testInfo) => { | 
					
						
							|  |  |  |   await context.tracing.start({ screenshots: true, snapshots: true }); | 
					
						
							|  |  |  |   let expectPromise; | 
					
						
							|  |  |  |   page.on('dialog', dialog => { | 
					
						
							|  |  |  |     expectPromise = expect(page).toHaveTitle('Hello'); | 
					
						
							|  |  |  |     dialog.dismiss(); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   await page.setContent(`<title>Hello</title><div onclick='window.alert(123)'>Click me</div>`); | 
					
						
							|  |  |  |   await page.click('div'); | 
					
						
							|  |  |  |   await expect(page.locator('div')).toBeVisible(); | 
					
						
							|  |  |  |   await expectPromise; | 
					
						
							|  |  |  |   const tracePath = testInfo.outputPath('trace.zip'); | 
					
						
							|  |  |  |   await context.tracing.stop({ path: tracePath }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(tracePath); | 
					
						
							|  |  |  |   const actions = trace.events.filter(e => e.type === 'action' && !e.metadata.apiName.startsWith('tracing.')); | 
					
						
							|  |  |  |   expect(actions).toHaveLength(5); | 
					
						
							|  |  |  |   for (const action of actions) | 
					
						
							|  |  |  |     expect(relativeStack(action)).toEqual(['tracing.spec.ts']); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-25 12:04:03 -08:00
										 |  |  | test('should record global request trace', async ({ request, context, server }, testInfo) => { | 
					
						
							|  |  |  |   await (request as any)._tracing.start({ snapshots: true }); | 
					
						
							|  |  |  |   const url = server.PREFIX + '/simple.json'; | 
					
						
							|  |  |  |   await request.get(url); | 
					
						
							|  |  |  |   const tracePath = testInfo.outputPath('trace.zip'); | 
					
						
							|  |  |  |   await (request as any)._tracing.stop({ path: tracePath }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(tracePath); | 
					
						
							|  |  |  |   const actions = trace.events.filter(e => e.type === 'resource-snapshot'); | 
					
						
							|  |  |  |   expect(actions).toHaveLength(1); | 
					
						
							|  |  |  |   expect(actions[0].snapshot.request).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |     method: 'GET', | 
					
						
							|  |  |  |     url | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  |   expect(actions[0].snapshot.response).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |     status: 200, | 
					
						
							|  |  |  |     statusText: 'OK', | 
					
						
							|  |  |  |     headers: expect.arrayContaining([ | 
					
						
							|  |  |  |       expect.objectContaining({ | 
					
						
							|  |  |  |         'name': 'Content-Length', | 
					
						
							|  |  |  |         'value': '15' | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     ]) | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 09:13:29 -07:00
										 |  |  | test('should store global request traces separately', async ({ request, server, playwright }, testInfo) => { | 
					
						
							| 
									
										
										
										
											2022-01-25 12:04:03 -08:00
										 |  |  |   const request2 = await playwright.request.newContext(); | 
					
						
							|  |  |  |   await Promise.all([ | 
					
						
							|  |  |  |     (request as any)._tracing.start({ snapshots: true }), | 
					
						
							|  |  |  |     (request2 as any)._tracing.start({ snapshots: true }) | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  |   const url = server.PREFIX + '/simple.json'; | 
					
						
							|  |  |  |   await Promise.all([ | 
					
						
							|  |  |  |     request.get(url), | 
					
						
							|  |  |  |     request2.post(url) | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  |   const tracePath = testInfo.outputPath('trace.zip'); | 
					
						
							|  |  |  |   const trace2Path = testInfo.outputPath('trace2.zip'); | 
					
						
							|  |  |  |   await Promise.all([ | 
					
						
							|  |  |  |     (request as any)._tracing.stop({ path: tracePath }), | 
					
						
							|  |  |  |     (request2 as any)._tracing.stop({ path: trace2Path }) | 
					
						
							|  |  |  |   ]); | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const trace = await parseTrace(tracePath); | 
					
						
							|  |  |  |     const actions = trace.events.filter(e => e.type === 'resource-snapshot'); | 
					
						
							|  |  |  |     expect(actions).toHaveLength(1); | 
					
						
							|  |  |  |     expect(actions[0].snapshot.request).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |       method: 'GET', | 
					
						
							|  |  |  |       url | 
					
						
							|  |  |  |     })); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     const trace = await parseTrace(trace2Path); | 
					
						
							|  |  |  |     const actions = trace.events.filter(e => e.type === 'resource-snapshot'); | 
					
						
							|  |  |  |     expect(actions).toHaveLength(1); | 
					
						
							|  |  |  |     expect(actions[0].snapshot.request).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |       method: 'POST', | 
					
						
							|  |  |  |       url | 
					
						
							|  |  |  |     })); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 09:13:29 -07:00
										 |  |  | test('should store postData for global request', async ({ request, server }, testInfo) => { | 
					
						
							|  |  |  |   testInfo.annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/15031' }); | 
					
						
							|  |  |  |   await (request as any)._tracing.start({ snapshots: true }); | 
					
						
							|  |  |  |   const url = server.PREFIX + '/simple.json'; | 
					
						
							|  |  |  |   await request.post(url, { | 
					
						
							|  |  |  |     data: 'test' | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  |   const tracePath = testInfo.outputPath('trace.zip'); | 
					
						
							|  |  |  |   await (request as any)._tracing.stop({ path: tracePath }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const trace = await parseTrace(tracePath); | 
					
						
							|  |  |  |   const actions = trace.events.filter(e => e.type === 'resource-snapshot'); | 
					
						
							|  |  |  |   expect(actions).toHaveLength(1); | 
					
						
							|  |  |  |   const req = actions[0].snapshot.request; | 
					
						
							|  |  |  |   expect(req.postData?._sha1).toBeTruthy(); | 
					
						
							|  |  |  |   expect(req).toEqual(expect.objectContaining({ | 
					
						
							|  |  |  |     method: 'POST', | 
					
						
							|  |  |  |     url | 
					
						
							|  |  |  |   })); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-11 13:21:01 -07:00
										 |  |  | function expectRed(pixels: Buffer, offset: number) { | 
					
						
							|  |  |  |   const r = pixels.readUInt8(offset); | 
					
						
							|  |  |  |   const g = pixels.readUInt8(offset + 1); | 
					
						
							|  |  |  |   const b = pixels.readUInt8(offset + 2); | 
					
						
							|  |  |  |   const a = pixels.readUInt8(offset + 3); | 
					
						
							|  |  |  |   expect(r).toBeGreaterThan(200); | 
					
						
							|  |  |  |   expect(g).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(b).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(a).toBe(255); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function expectBlue(pixels: Buffer, offset: number) { | 
					
						
							|  |  |  |   const r = pixels.readUInt8(offset); | 
					
						
							|  |  |  |   const g = pixels.readUInt8(offset + 1); | 
					
						
							|  |  |  |   const b = pixels.readUInt8(offset + 2); | 
					
						
							|  |  |  |   const a = pixels.readUInt8(offset + 3); | 
					
						
							|  |  |  |   expect(r).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(g).toBeLessThan(70); | 
					
						
							|  |  |  |   expect(b).toBeGreaterThan(200); | 
					
						
							|  |  |  |   expect(a).toBe(255); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-10-25 10:49:59 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | function relativeStack(action: any): string[] { | 
					
						
							|  |  |  |   return action.metadata.stack.map(f => f.file.replace(__dirname + path.sep, '')); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-07-15 22:31:58 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | function eventsToActions(events: any[]): string[] { | 
					
						
							|  |  |  |   return events.filter(e => e.type === 'action' && !e.metadata.internal) | 
					
						
							|  |  |  |       .sort((a, b) => a.metadata.startTime - b.metadata.startTime) | 
					
						
							|  |  |  |       .map(e => e.metadata.apiName); | 
					
						
							|  |  |  | } |