@@ -40,16 +40,20 @@ declare global {
4040 /**
4141 * Asserts that the element never gains the given attribute.
4242 *
43- * __Note:__ An error is thrown if the attribute is not found, therefore it does not block the test if the subject
43+ * __Note:__ An error is thrown if the attribute is found, therefore it does not block the test if the subject
4444 * never includes the given attribute.
4545 *
46- *
4746 * @param attributeName - The name of the attribute which must not appear.
48- * @param observerTime - How long (in ms) to watch for mutations (default: 500).
47+ * @param options
48+ * @param options.observerTime - How long (in ms) to watch for mutations (default: 500).
49+ * @param options.delayed - How long (in ms) to wait before starting observation (default: 0).
4950 * @example
50- * cy.get('button').shouldNeverHaveAttribute('disabled', 1000 );
51+ * cy.get('button').shouldNeverHaveAttribute('disabled', { observerTime: 500, delayed: 100 } );
5152 */
52- shouldNeverHaveAttribute ( attributeName : string , observerTime ?: number ) : Chainable < JQuery < HTMLElement > > ;
53+ shouldNeverHaveAttribute (
54+ attributeName : string ,
55+ options ?: { observerTime ?: number ; delayed ?: number } ,
56+ ) : Chainable < JQuery < HTMLElement > > ;
5357 }
5458 }
5559}
@@ -80,35 +84,49 @@ Cypress.Commands.add(
8084 } ,
8185) ;
8286
83- Cypress . Commands . add (
84- 'shouldNeverHaveAttribute' ,
85- { prevSubject : 'element' } ,
86- ( subject , attributeName , observerTime = 500 ) => {
87- cy . wrap ( subject ) . then ( ( $el ) => {
88- const el = $el [ 0 ] ;
89- const observer = new MutationObserver ( ( mutations ) => {
90- for ( const mutation of mutations ) {
91- if ( mutation . attributeName === attributeName ) {
92- Cypress . log ( {
93- name : 'shouldNeverHaveAttribute' ,
94- message : `${ attributeName } was found!` ,
95- consoleProps : ( ) => ( {
96- attributeName,
97- element : el ,
98- } ) ,
99- } ) ;
87+ const activeObservers : MutationObserver [ ] = [ ] ;
10088
101- observer . disconnect ( ) ;
102- throw new Error ( `${ attributeName } was found!` ) ;
103- }
104- }
105- } ) ;
89+ Cypress . Commands . add ( 'shouldNeverHaveAttribute' , { prevSubject : 'element' } , ( subject , attributeName , options = { } ) => {
90+ const { observerTime = 500 , delayed = 0 } = options ;
91+ // Disconnect all previous observers when a new assertion starts
92+ while ( activeObservers . length > 0 ) {
93+ activeObservers . pop ( ) ?. disconnect ( ) ;
94+ }
95+
96+ cy . wait ( delayed ) ;
10697
107- observer . observe ( el , { attributes : true } ) ;
98+ cy . wrap ( subject ) . then ( ( $el ) => {
99+ const el = $el [ 0 ] ;
100+ const observer = new MutationObserver ( ( mutations ) => {
101+ for ( const mutation of mutations ) {
102+ if ( mutation . attributeName === attributeName ) {
103+ Cypress . log ( {
104+ name : 'shouldNeverHaveAttribute' ,
105+ message : `${ attributeName } was found!` ,
106+ consoleProps : ( ) => ( {
107+ attributeName,
108+ element : el ,
109+ } ) ,
110+ } ) ;
108111
109- setTimeout ( ( ) => {
110- observer . disconnect ( ) ;
111- } , observerTime ) ;
112+ observer . disconnect ( ) ;
113+ const index = activeObservers . indexOf ( observer ) ;
114+ if ( index > - 1 ) {
115+ activeObservers . splice ( index , 1 ) ;
116+ }
117+ throw new Error ( `${ attributeName } was found!` ) ;
118+ }
119+ }
112120 } ) ;
113- } ,
114- ) ;
121+ observer . observe ( el , { attributes : true } ) ;
122+ activeObservers . push ( observer ) ;
123+
124+ setTimeout ( ( ) => {
125+ observer . disconnect ( ) ;
126+ const index = activeObservers . indexOf ( observer ) ;
127+ if ( index > - 1 ) {
128+ activeObservers . splice ( index , 1 ) ;
129+ }
130+ } , observerTime ) ;
131+ } ) ;
132+ } ) ;
0 commit comments