2023-03-18 04:20:35 +01: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-04-28 23:18:46 +02:00
import { createImage } from './playwright-test-fixtures' ;
2023-05-18 20:28:28 +02:00
import { test , expect , retries } from './ui-mode-fixtures' ;
test . describe . configure ( { mode : 'parallel' , retries } ) ;
2023-03-18 04:20:35 +01:00
2023-11-28 01:43:47 +01:00
test ( 'should merge trace events' , async ( { runUITest } ) = > {
2023-03-29 22:57:19 +02:00
const { page } = await runUITest ( {
2023-03-18 04:20:35 +01:00
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { page } ) = > {
await page . setContent ( '<button>Submit</button>' ) ;
expect ( 1 ) . toBe ( 1 ) ;
await page . getByRole ( 'button' ) . click ( ) ;
expect ( 2 ) . toBe ( 2 ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-03-18 04:20:35 +01:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
2023-05-06 00:12:18 +02:00
/Before Hooks[\d.]+m?s/ ,
/page.setContent[\d.]+m?s/ ,
/expect.toBe[\d.]+m?s/ ,
/locator.clickgetByRole\('button'\)[\d.]+m?s/ ,
/expect.toBe[\d.]+m?s/ ,
/After Hooks[\d.]+m?s/ ,
2023-04-28 23:18:46 +02:00
] ) ;
2023-03-18 04:20:35 +01:00
} ) ;
2023-04-21 19:07:23 +02:00
test ( 'should merge web assertion events' , async ( { runUITest } , testInfo ) = > {
const { page } = await runUITest ( {
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { page } ) = > {
await page . setContent ( '<button>Submit</button>' ) ;
await expect ( page . locator ( 'button' ) ) . toBeVisible ( ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-04-21 19:07:23 +02:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
2023-05-06 00:12:18 +02:00
/Before Hooks[\d.]+m?s/ ,
/page.setContent[\d.]+m?s/ ,
/expect.toBeVisiblelocator\('button'\)[\d.]+m?s/ ,
/After Hooks[\d.]+m?s/ ,
2023-04-28 23:18:46 +02:00
] ) ;
2023-04-21 19:07:23 +02:00
} ) ;
test ( 'should merge screenshot assertions' , async ( { runUITest } , testInfo ) = > {
const { page } = await runUITest ( {
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { page } ) = > {
await page . setContent ( '<button>Submit</button>' ) ;
await expect ( page . locator ( 'button' ) ) . toHaveScreenshot ( ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-04-21 19:07:23 +02:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
2023-05-06 00:12:18 +02:00
/Before Hooks[\d.]+m?s/ ,
2023-05-19 00:52:44 +02:00
/page.setContent[\d.]+m?s/ ,
/expect.toHaveScreenshot[\d.]+m?s/ ,
2024-07-18 11:42:44 +02:00
/attach "trace-test-1-expected.png/ ,
2023-10-26 02:05:06 +02:00
/attach "trace-test-1-actual.png/ ,
2023-05-23 18:36:35 +02:00
/After Hooks[\d.]+m?s/ ,
2024-03-09 00:19:36 +01:00
/Worker Cleanup[\d.]+m?s/ ,
2023-04-28 23:18:46 +02:00
] ) ;
2023-04-21 19:07:23 +02:00
} ) ;
2023-11-28 01:43:47 +01:00
test ( 'should locate sync assertions in source' , async ( { runUITest } ) = > {
2023-03-29 22:57:19 +02:00
const { page } = await runUITest ( {
2023-03-18 04:20:35 +01:00
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { } ) = > {
expect ( 1 ) . toBe ( 1 ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
2023-05-06 00:12:18 +02:00
await page . getByText ( 'expect.toBe' ) . click ( ) ;
2023-03-18 04:20:35 +01:00
await expect (
page . locator ( '.CodeMirror .source-line-running' ) ,
'check source tab' ,
2023-04-28 23:18:46 +02:00
) . toHaveText ( '4 expect(1).toBe(1);' ) ;
2023-03-18 04:20:35 +01:00
} ) ;
2023-11-28 01:43:47 +01:00
test ( 'should show snapshots for sync assertions' , async ( { runUITest } ) = > {
2023-03-29 22:57:19 +02:00
const { page } = await runUITest ( {
2023-03-18 04:20:35 +01:00
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { page } ) = > {
await page . setContent ( '<button>Submit</button>' ) ;
await page . getByRole ( 'button' ) . click ( ) ;
expect ( 1 ) . toBe ( 1 ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-03-18 04:20:35 +01:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
2023-05-06 00:12:18 +02:00
/Before Hooks[\d.]+m?s/ ,
2023-03-18 04:20:35 +01:00
/page\.setContent[\d.]+m?s/ ,
/locator\.clickgetByRole\('button'\)[\d.]+m?s/ ,
/expect\.toBe[\d.]+m?s/ ,
2023-05-06 00:12:18 +02:00
/After Hooks[\d.]+m?s/ ,
2023-04-28 23:18:46 +02:00
] ) ;
2023-03-18 04:20:35 +01:00
await expect (
2023-03-21 15:40:54 +01:00
page . frameLocator ( 'iframe.snapshot-visible[name=snapshot]' ) . locator ( 'button' ) ,
2023-03-18 04:20:35 +01:00
'verify snapshot'
) . toHaveText ( 'Submit' ) ;
} ) ;
2023-04-28 23:18:46 +02:00
2023-11-28 01:43:47 +01:00
test ( 'should show image diff' , async ( { runUITest } ) = > {
2023-04-28 23:18:46 +02:00
const { page } = await runUITest ( {
'playwright.config.js' : `
module .exports = {
snapshotPathTemplate : '{arg}{ext}'
} ;
` ,
'snapshot.png' : createImage ( 100 , 100 , 255 , 0 , 0 ) ,
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'vrt test' , async ( { page } ) = > {
await page . setViewportSize ( { width : 100 , height : 100 } ) ;
await expect ( page ) . toHaveScreenshot ( 'snapshot.png' , { timeout : 2000 } ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'vrt test' ) . dblclick ( ) ;
2023-05-10 02:53:01 +02:00
await page . getByText ( /Attachments/ ) . click ( ) ;
2023-04-28 23:18:46 +02:00
await expect ( page . getByText ( 'Diff' , { exact : true } ) ) . toBeVisible ( ) ;
await expect ( page . getByText ( 'Actual' , { exact : true } ) ) . toBeVisible ( ) ;
await expect ( page . getByText ( 'Expected' , { exact : true } ) ) . toBeVisible ( ) ;
2023-12-22 19:17:35 +01:00
await expect ( page . getByTestId ( 'test-result-image-mismatch' ) . locator ( 'img' ) ) . toBeVisible ( ) ;
2023-04-28 23:18:46 +02:00
} ) ;
2023-06-02 05:29:32 +02:00
2023-11-28 01:43:47 +01:00
test ( 'should show screenshot' , async ( { runUITest } ) = > {
2023-06-02 05:29:32 +02:00
const { page } = await runUITest ( {
'playwright.config.js' : `
module .exports = {
use : {
screenshot : 'on' ,
viewport : { width : 100 , height : 100 }
}
} ;
` ,
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'vrt test' , async ( { page } ) = > {
} ) ;
` ,
} ) ;
await page . getByText ( 'vrt test' ) . dblclick ( ) ;
await page . getByText ( /Attachments/ ) . click ( ) ;
await expect ( page . getByText ( 'Screenshots' , { exact : true } ) ) . toBeVisible ( ) ;
await expect ( page . locator ( '.attachment-item img' ) ) . toHaveCount ( 1 ) ;
} ) ;
2023-11-28 01:43:47 +01:00
test ( 'should not fail on internal page logs' , async ( { runUITest , server } ) = > {
const { page } = await runUITest ( {
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { browser } , testInfo ) = > {
const context = await browser . newContext ( { storageState : { cookies : [ ] , origins : [ ] } } ) ;
const page = await context . newPage ( ) ;
await page . goto ( "${server.EMPTY_PAGE}" ) ;
await page . context ( ) . storageState ( { path : testInfo.outputPath ( 'storage.json' ) } ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-11-28 01:43:47 +01:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
/Before Hooks[\d.]+m?s/ ,
/browser.newContext[\d.]+m?s/ ,
/browserContext.newPage[\d.]+m?s/ ,
/page.goto/ ,
/browserContext.storageState[\d.]+m?s/ ,
/After Hooks/ ,
] ) ;
} ) ;
2023-12-22 23:19:53 +01:00
test ( 'should not show caught errors in the errors tab' , async ( { runUITest } , testInfo ) = > {
const { page } = await runUITest ( {
'a.spec.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { page } , testInfo ) = > {
await page . setContent ( "<input id='checkbox' type='checkbox'></input>" ) ;
await expect ( page . locator ( 'input' ) ) . toBeChecked ( { timeout : 1 } ) . catch ( ( ) = > { } ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2023-12-22 23:19:53 +01:00
await expect (
listItem ,
'action list'
) . toHaveText ( [
/Before Hooks[\d.]+m?s/ ,
/page.setContent/ ,
/expect.toBeCheckedlocator.*[\d.]+m?s/ ,
/After Hooks/ ,
] ) ;
await page . getByText ( 'Source' , { exact : true } ) . click ( ) ;
await expect ( page . locator ( '.source-line-running' ) ) . toContainText ( 'toBeChecked' ) ;
await expect ( page . locator ( '.CodeMirror-linewidget' ) ) . toHaveCount ( 0 ) ;
await page . getByText ( 'Errors' , { exact : true } ) . click ( ) ;
await expect ( page . locator ( '.tab-errors' ) ) . toHaveText ( 'No errors' ) ;
} ) ;
2024-02-01 17:23:07 +01:00
2024-11-13 17:32:32 +01:00
test ( 'should show errors with causes in the error tab' , async ( { runUITest } ) = > {
const { page } = await runUITest ( {
'a.spec.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { page } ) = > {
try {
try {
const error = new Error ( 'my-message' ) ;
error . name = 'SpecialError' ;
throw error ;
} catch ( e ) {
try {
throw new Error ( 'inner-message' , { cause : e } ) ;
} catch ( e ) {
throw new Error ( 'outer-message' , { cause : e } ) ;
}
}
} catch ( e ) {
throw new Error ( 'wrapper-message' , { cause : e } ) ;
}
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
await page . getByText ( 'Errors' , { exact : true } ) . click ( ) ;
await expect ( page . locator ( '.tab-errors' ) ) . toContainText ( ` Error: wrapper-message
[ cause ] : Error : outer - message
[ cause ] : Error : inner - message
[ cause ] : SpecialError : my - message ` );
} ) ;
2024-02-01 17:23:07 +01:00
test ( 'should reveal errors in the sourcetab' , async ( { runUITest } ) = > {
const { page } = await runUITest ( {
'a.spec.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { page } ) = > {
throw new Error ( 'Oh my' ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
2024-10-18 01:57:45 +02:00
const listItem = page . getByTestId ( 'actions-tree' ) . getByRole ( 'treeitem' ) ;
2024-02-01 17:23:07 +01:00
await expect (
listItem ,
'action list'
) . toContainText ( [
/Before Hooks/ ,
/After Hooks/ ,
] ) ;
await page . getByText ( 'Errors' , { exact : true } ) . click ( ) ;
await page . getByText ( 'a.spec.ts:4' , { exact : true } ) . click ( ) ;
await expect ( page . locator ( '.source-line-running' ) ) . toContainText ( ` throw new Error('Oh my'); ` ) ;
} ) ;
2024-05-16 01:29:26 +02:00
test ( 'should show request source context id' , async ( { runUITest , server } ) = > {
const { page } = await runUITest ( {
'a.spec.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { page , context , request } ) = > {
await page . goto ( '${server.EMPTY_PAGE}' ) ;
const page2 = await context . newPage ( ) ;
await page2 . goto ( '${server.EMPTY_PAGE}' ) ;
await request . get ( '${server.EMPTY_PAGE}' ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
await page . getByText ( 'Network' , { exact : true } ) . click ( ) ;
await expect ( page . locator ( 'span' ) . filter ( { hasText : 'Source' } ) ) . toBeVisible ( ) ;
await expect ( page . getByText ( 'page#1' ) ) . toBeVisible ( ) ;
await expect ( page . getByText ( 'page#2' ) ) . toBeVisible ( ) ;
await expect ( page . getByText ( 'api#1' ) ) . toBeVisible ( ) ;
} ) ;
2024-11-26 14:10:26 +01:00
test ( 'should work behind proxy' , { annotation : { type : 'issue' , description : 'https://github.com/microsoft/playwright/issues/33705' } } , async ( { runUITest , proxyServer } , testInfo ) = > {
const { page } = await runUITest ( {
'a.test.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'trace test' , async ( { page } ) = > {
await page . setContent ( '<button>Submit</button>' ) ;
await page . getByRole ( 'button' ) . click ( ) ;
expect ( 1 ) . toBe ( 1 ) ;
} ) ;
` ,
} ) ;
const origin = new URL ( page . url ( ) ) ;
proxyServer . forwardTo ( + origin . port , { prefix : '/subdir' } ) ;
await page . goto ( ` ${ proxyServer . URL } /subdir ${ origin . pathname } ? ${ origin . searchParams } ` ) ;
await page . getByText ( 'trace test' ) . dblclick ( ) ;
await expect ( page . getByTestId ( 'actions-tree' ) ) . toMatchAriaSnapshot ( `
- tree :
- treeitem / Before Hooks \ \ d + [ hmsp ] + /
- treeitem / page \ \ . setContent \ \ d + [ hmsp ] + /
- treeitem / locator \ \ . clickgetByRole \ \ ( 'button' \ \ ) \ \ d + [ hmsp ] + /
- treeitem / expect \ \ . toBe \ \ d + [ hmsp ] + / [ s e l e c t e d ]
- treeitem / After Hooks \ \ d + [ hmsp ] + /
` );
await expect (
page . frameLocator ( 'iframe.snapshot-visible[name=snapshot]' ) . locator ( 'button' ) ,
) . toHaveText ( 'Submit' ) ;
2024-11-29 13:55:33 +01:00
} ) ;
2024-11-28 14:04:34 +01:00
test ( 'should filter actions tab on double-click' , async ( { runUITest , server } ) = > {
const { page } = await runUITest ( {
'a.spec.ts' : `
import { test , expect } from '@playwright/test' ;
test ( 'pass' , async ( { page } ) = > {
await page . goto ( '${server.EMPTY_PAGE}' ) ;
} ) ;
` ,
} ) ;
await page . getByText ( 'pass' ) . dblclick ( ) ;
const actionsTree = page . getByTestId ( 'actions-tree' ) ;
await expect ( actionsTree . getByRole ( 'treeitem' ) ) . toHaveText ( [
/Before Hooks/ ,
/page.goto/ ,
/After Hooks/ ,
] ) ;
await actionsTree . getByRole ( 'treeitem' , { name : 'page.goto' } ) . dblclick ( ) ;
await expect ( actionsTree . getByRole ( 'treeitem' ) ) . toHaveText ( [
/page.goto/ ,
] ) ;
} ) ;