2023-10-31 09:33:13 -04:00
import type { Locator , Page } from '@playwright/test'
2023-09-01 17:39:44 +02:00
2022-07-13 11:00:10 -07:00
import { expect } from '@playwright/test'
2023-11-28 16:54:34 -05:00
import shelljs from 'shelljs'
2023-09-01 17:39:44 +02:00
2023-09-01 14:45:41 -04:00
import wait from '../packages/payload/src/utilities/wait'
2022-07-15 12:51:43 -07:00
import { devUser } from './credentials'
2022-07-13 11:00:10 -07:00
type FirstRegisterArgs = {
2022-07-17 08:20:01 -07:00
page : Page
serverURL : string
}
2022-07-13 11:00:10 -07:00
type LoginArgs = {
2022-07-17 08:20:01 -07:00
page : Page
serverURL : string
}
2022-07-13 11:00:10 -07:00
export async function firstRegister ( args : FirstRegisterArgs ) : Promise < void > {
const { page , serverURL } = args
2023-09-01 17:39:44 +02:00
2022-07-13 11:00:10 -07:00
await page . goto ( ` ${ serverURL } /admin ` )
2022-07-14 17:00:34 -04:00
await page . fill ( '#field-email' , devUser . email )
await page . fill ( '#field-password' , devUser . password )
await page . fill ( '#field-confirm-password' , devUser . password )
2022-07-13 11:00:10 -07:00
await wait ( 500 )
await page . click ( '[type=submit]' )
await page . waitForURL ( ` ${ serverURL } /admin ` )
}
export async function login ( args : LoginArgs ) : Promise < void > {
const { page , serverURL } = args
2023-09-01 17:39:44 +02:00
2022-07-13 11:00:10 -07:00
await page . goto ( ` ${ serverURL } /admin ` )
2022-07-14 17:00:34 -04:00
await page . fill ( '#field-email' , devUser . email )
await page . fill ( '#field-password' , devUser . password )
2022-07-13 11:00:10 -07:00
await wait ( 500 )
await page . click ( '[type=submit]' )
await page . waitForURL ( ` ${ serverURL } /admin ` )
}
2023-08-14 21:36:49 +02:00
export async function saveDocHotkeyAndAssert ( page : Page ) : Promise < void > {
const ua = page . evaluate ( ( ) = > navigator . userAgent )
const isMac = ( await ua ) . includes ( 'Mac OS X' )
if ( isMac ) {
await page . keyboard . down ( 'Meta' )
} else {
await page . keyboard . down ( 'Control' )
}
await page . keyboard . down ( 's' )
await expect ( page . locator ( '.Toastify' ) ) . toContainText ( 'successfully' )
}
2024-06-13 11:08:04 -04:00
export async function saveDocAndAssert (
page : Page ,
selector = '#action-save' ,
expectation : 'error' | 'success' = 'success' ,
) : Promise < void > {
2023-03-06 17:06:37 -05:00
await page . click ( selector , { delay : 100 } )
2024-06-13 11:08:04 -04:00
if ( expectation === 'success' ) {
await expect ( page . locator ( '.Toastify' ) ) . toContainText ( 'successfully' )
expect ( page . url ( ) ) . not . toContain ( 'create' )
} else {
await expect ( page . locator ( '.Toastify .Toastify__toast--error' ) ) . toBeVisible ( )
}
2022-07-13 11:00:10 -07:00
}
2023-09-15 16:40:08 -04:00
2023-09-29 13:10:37 -04:00
export async function openNav ( page : Page ) : Promise < void > {
// check to see if the nav is already open and if not, open it
// use the `--nav-open` modifier class to check if the nav is open
// this will prevent clicking nav links that are bleeding off the screen
if ( await page . locator ( '.template-default.template-default--nav-open' ) . isVisible ( ) ) return
await page . locator ( '#nav-toggler' ) . click ( )
await expect ( await page . locator ( '.template-default.template-default--nav-open' ) ) . toBeVisible ( )
2023-09-15 16:40:08 -04:00
}
2023-09-29 13:10:37 -04:00
export async function closeNav ( page : Page ) : Promise < void > {
if ( ! ( await page . locator ( '.template-default.template-default--nav-open' ) . isVisible ( ) ) ) return
await page . locator ( '#nav-toggler' ) . click ( )
await expect ( await page . locator ( '.template-default.template-default--nav-open' ) ) . toBeHidden ( )
2023-09-15 16:40:08 -04:00
}
2023-09-15 17:33:28 -04:00
export async function openDocControls ( page : Page ) : Promise < void > {
await page . locator ( '.doc-controls__popup .popup-button' ) . click ( )
await expect ( page . locator ( '.doc-controls__popup .popup__content' ) ) . toBeVisible ( )
}
2023-09-15 16:40:08 -04:00
export async function changeLocale ( page : Page , newLocale : string ) {
await page . locator ( '.localizer >> button' ) . first ( ) . click ( )
2023-12-19 09:57:46 -05:00
await page . locator ( ` .localizer >> a[href="/?locale= ${ newLocale } "] ` ) . click ( )
2023-09-15 16:40:08 -04:00
expect ( page . url ( ) ) . toContain ( ` locale= ${ newLocale } ` )
}
2023-09-27 13:18:29 -04:00
export function exactText ( text : string ) {
return new RegExp ( ` ^ ${ text } $ ` )
}
2023-10-31 09:33:13 -04:00
2023-11-01 08:58:42 -04:00
export const checkPageTitle = async ( page : Page , title : string ) = >
expect ( await page . locator ( '.doc-header__title.render-title' ) ? . first ( ) ? . innerText ( ) ) . toBe ( title )
export const checkBreadcrumb = async ( page : Page , text : string ) = >
expect ( await page . locator ( '.step-nav.app-header__step-nav .step-nav__last' ) ? . innerText ( ) ) . toBe (
text ,
)
2023-10-31 09:33:13 -04:00
export const selectTableRow = async ( page : Page , title : string ) : Promise < void > = > {
const selector = ` tbody tr:has-text(" ${ title } ") .select-row__checkbox input[type=checkbox] `
await page . locator ( selector ) . check ( )
expect ( await page . locator ( selector ) . isChecked ( ) ) . toBe ( true )
}
2024-06-07 09:47:35 -04:00
export async function navigateToListCellLink ( page : Page , selector = '.cell-id' ) {
const cellLink = page . locator ( ` ${ selector } a ` ) . first ( )
const linkURL = await cellLink . getAttribute ( 'href' )
await cellLink . click ( )
await page . waitForURL ( ` ** ${ linkURL } ` )
}
2023-10-31 09:33:13 -04:00
export const findTableCell = async (
page : Page ,
fieldName : string ,
rowTitle? : string ,
) : Promise < Locator > = > {
const parentEl = rowTitle ? await findTableRow ( page , rowTitle ) : page . locator ( 'tbody tr' )
const cell = parentEl . locator ( ` td.cell- ${ fieldName } ` )
expect ( cell ) . toBeTruthy ( )
return cell
}
export const findTableRow = async ( page : Page , title : string ) : Promise < Locator > = > {
const row = page . locator ( ` tbody tr:has-text(" ${ title } ") ` )
expect ( row ) . toBeTruthy ( )
return row
}
2023-11-16 22:01:04 +01:00
/**
* Throws an error when browser console error messages (with some exceptions) are thrown, thus resulting
* in the e2e test failing.
*
* Useful to prevent the e2e test from passing when, for example, there are react missing key prop errors
* @param page
*/
export function initPageConsoleErrorCatch ( page : Page ) {
page . on ( 'console' , ( msg ) = > {
if ( msg . type ( ) === 'error' && ! msg . text ( ) . includes ( 'the server responded with a status of' ) ) {
// the the server responded with a status of error happens frequently. Will ignore it for now.
// Most importantly, this should catch react errors.
throw new Error ( ` Browser console error: ${ msg . text ( ) } ` )
}
} )
}
2023-11-28 16:54:34 -05:00
export function describeIfInCIOrHasLocalstack ( ) : jest . Describe {
if ( process . env . CI ) {
return describe
}
// Check that localstack is running
const { code } = shelljs . exec ( ` docker ps | grep localstack ` )
if ( code !== 0 ) {
2024-02-16 12:33:07 -05:00
console . warn ( 'Localstack is not running. Skipping test suite.' )
2023-11-28 16:54:34 -05:00
return describe . skip
}
2024-02-16 12:33:07 -05:00
console . log ( 'Localstack is running. Running test suite.' )
2023-11-28 16:54:34 -05:00
return describe
}