1
1
import { Locator , expect } from '@playwright/test' ;
2
- import { throwTimeoutError } from './utils/utils' ;
2
+
3
+ class SoftAssertionError extends Error {
4
+ name = 'SoftAssertionError' ;
5
+ }
3
6
4
7
export const conditionValidations = {
5
8
PRESENT : 'present' ,
6
- // CLICKABLE: 'clickable',
9
+ CLICKABLE : 'clickable' ,
7
10
VISIBLE : 'visible' ,
8
11
INVISIBLE : 'invisible' ,
9
12
IN_VIEWPORT : 'in viewport' ,
@@ -13,57 +16,58 @@ export const conditionValidations = {
13
16
14
17
const notClause = '(not )?' ;
15
18
const toBeClause = 'to (?:be )?' ;
19
+ const softClause = '(softly )?'
16
20
const validationClause = `(${ Object . values ( conditionValidations ) . join ( '|' ) } )` ;
17
21
18
- export const conditionWaitExtractRegexp = new RegExp ( `^${ notClause } ${ toBeClause } ${ validationClause } $` ) ;
19
- export const conditionWaitRegexp = new RegExp ( `(${ notClause } ${ toBeClause } ${ validationClause } )` ) ;
22
+ export const conditionWaitExtractRegexp = new RegExp ( `^${ notClause } ${ toBeClause } ${ softClause } ${ validationClause } $` ) ;
20
23
24
+ const makeExpect = ( element : Locator , reverse : boolean , message : string ) => {
25
+ const eMessage = expect ( element , message ) ;
26
+ return reverse ? eMessage . not : eMessage ;
27
+ }
21
28
const waits = {
22
29
[ conditionValidations . PRESENT ] : (
23
30
element : Locator ,
24
31
reverse : boolean ,
25
32
timeout : number ,
26
33
timeoutMsg : string
27
- ) => element . waitFor ( { state : reverse ? 'detached' : 'attached' , timeout } ) ,
34
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeAttached ( { timeout } ) ,
28
35
[ conditionValidations . VISIBLE ] : (
29
36
element : Locator ,
30
37
reverse : boolean ,
31
38
timeout : number ,
32
39
timeoutMsg : string
33
- ) => element . waitFor ( { state : reverse ? 'hidden' : 'visible' , timeout } ) ,
40
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeVisible ( { timeout } ) ,
34
41
[ conditionValidations . INVISIBLE ] : (
35
42
element : Locator ,
36
43
reverse : boolean ,
37
44
timeout : number ,
38
45
timeoutMsg : string
39
- ) => element . waitFor ( { state : reverse ? 'visible' : 'hidden' , timeout } ) ,
46
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeHidden ( { timeout } ) ,
40
47
[ conditionValidations . IN_VIEWPORT ] : (
41
48
element : Locator ,
42
49
reverse : boolean ,
43
50
timeout : number ,
44
51
timeoutMsg : string
45
- ) => throwTimeoutError ( ( ) => expect ( async ( ) => {
46
- const e = reverse ? expect ( element ) . not : expect ( element ) ;
47
- await e . toBeInViewport ( ) ;
48
- } ) . toPass ( { timeout } ) , timeoutMsg ) ,
52
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeInViewport ( { timeout } ) ,
49
53
[ conditionValidations . ENABLED ] : (
50
54
element : Locator ,
51
55
reverse : boolean ,
52
56
timeout : number ,
53
57
timeoutMsg : string
54
- ) => throwTimeoutError ( ( ) => expect ( async ( ) => {
55
- const e = reverse ? expect ( element ) . not : expect ( element ) ;
56
- await e . toBeEnabled ( ) ;
57
- } ) . toPass ( { timeout } ) , timeoutMsg ) ,
58
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeEnabled ( { timeout } ) ,
58
59
[ conditionValidations . DISABLED ] : (
59
60
element : Locator ,
60
61
reverse : boolean ,
61
62
timeout : number ,
62
63
timeoutMsg : string
63
- ) => throwTimeoutError ( ( ) => expect ( async ( ) => {
64
- const e = reverse ? expect ( element ) . not : expect ( element ) ;
65
- await e . toBeDisabled ( ) ;
66
- } ) . toPass ( { timeout } ) , timeoutMsg )
64
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeDisabled ( { timeout } ) ,
65
+ [ conditionValidations . CLICKABLE ] : (
66
+ element : Locator ,
67
+ reverse : boolean ,
68
+ timeout : number ,
69
+ timeoutMsg : string
70
+ ) => makeExpect ( element , reverse , timeoutMsg ) . toBeEnabled ( { timeout } ) ,
67
71
}
68
72
/**
69
73
* Wait for condition
@@ -78,8 +82,22 @@ export async function conditionWait(
78
82
validationType : string ,
79
83
timeout : number = 10000 ,
80
84
reverse : boolean = false
81
- ) {
85
+ ) : Promise < void > {
82
86
const timeoutMsg : string = `Element is${ reverse ? '' : ' not' } ${ validationType } ` ;
83
87
const waitFn = waits [ validationType ] ;
84
88
await waitFn ( element , reverse , timeout , timeoutMsg ) ;
85
89
}
90
+
91
+ export function getConditionWait ( condition : string ) : Function {
92
+ const match = condition . match ( conditionWaitExtractRegexp ) as RegExpMatchArray ;
93
+ if ( ! match ) throw new Error ( `${ condition } wait is not implemented` ) ;
94
+ const [ _ , reverse , soft , validation ] = match ;
95
+ return async function ( element : Locator , timeout : number ) {
96
+ try {
97
+ await conditionWait ( element , validation , timeout , Boolean ( reverse ) )
98
+ } catch ( error ) {
99
+ if ( soft && error instanceof Error ) throw new SoftAssertionError ( error . message , { cause : error } ) ;
100
+ throw error ;
101
+ }
102
+ }
103
+ }
0 commit comments