11import { expect , test } from '@playwright/test' ;
2- import { INTEGRATIONS_PATH } from './test-utils' ;
2+ import { INTEGRATIONS_PATH , dismissCookieConsent } from './test-utils' ;
33import { generateCommunicationPayload , generateWebhookPayload } from './utils/data-generators' ;
44import {
5+ deleteIntegration ,
56 fillCommunicationForm ,
67 fillWebhookForm ,
78 waitForSuccessNotification ,
@@ -23,37 +24,37 @@ import {
2324test . describe ( 'Integrations Navigation' , ( ) => {
2425 test ( 'should navigate across all tabs' , async ( { page } ) => {
2526 await page . goto ( INTEGRATIONS_PATH ) ;
26- await page . waitForLoadState ( 'networkidle ' ) ;
27+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
2728 await expect ( page ) . toHaveURL ( / s e t t i n g s \/ i n t e g r a t i o n s / ) ;
2829
2930 await test . step ( 'Communications tab loads' , async ( ) => {
3031 const communicationsTab = page
3132 . locator ( 'button:has-text("Communications"), a:has-text("Communications")' )
3233 . first ( ) ;
33- if ( await communicationsTab . isVisible ( ) ) {
34- await communicationsTab . click ( ) ;
35- await page . waitForLoadState ( 'networkidle ' ) ;
36- }
34+ await expect ( communicationsTab ) . toBeVisible ( { timeout : 5000 } ) ;
35+ await communicationsTab . click ( ) ;
36+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
37+ await expect ( page ) . toHaveURL ( / c o m m u n i c a t i o n s / ) ;
3738 } ) ;
3839
3940 await test . step ( 'Reporting tab loads' , async ( ) => {
4041 const reportingTab = page
4142 . locator ( 'button:has-text("Reporting"), a:has-text("Reporting")' )
4243 . first ( ) ;
43- if ( await reportingTab . isVisible ( ) ) {
44- await reportingTab . click ( ) ;
45- await page . waitForLoadState ( 'networkidle ' ) ;
46- }
44+ await expect ( reportingTab ) . toBeVisible ( { timeout : 5000 } ) ;
45+ await reportingTab . click ( ) ;
46+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
47+ await expect ( page ) . toHaveURL ( / r e p o r t i n g / ) ;
4748 } ) ;
4849
4950 await test . step ( 'Webhooks tab loads' , async ( ) => {
5051 const webhooksTab = page
5152 . locator ( 'button:has-text("Webhooks"), a:has-text("Webhooks")' )
5253 . first ( ) ;
53- if ( await webhooksTab . isVisible ( ) ) {
54- await webhooksTab . click ( ) ;
55- await page . waitForLoadState ( 'networkidle ' ) ;
56- }
54+ await expect ( webhooksTab ) . toBeVisible ( { timeout : 5000 } ) ;
55+ await webhooksTab . click ( ) ;
56+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
57+ await expect ( page ) . toHaveURL ( / w e b h o o k s / ) ;
5758 } ) ;
5859 } ) ;
5960} ) ;
@@ -68,16 +69,9 @@ test.describe('Webhook Integration Lifecycle', () => {
6869
6970 // Navigate to integrations page
7071 await page . goto ( INTEGRATIONS_PATH ) ;
71- await page . waitForLoadState ( 'networkidle ' ) ;
72+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
7273
73- // Dismiss cookie consent if it appears
74- const acceptCookies = page
75- . getByRole ( 'button' , { name : 'Accept all' } )
76- . or ( page . getByRole ( 'button' , { name : 'Accept' } ) ) ;
77- if ( await acceptCookies . isVisible ( { timeout : 2000 } ) . catch ( ( ) => false ) ) {
78- await acceptCookies . click ( ) ;
79- await page . waitForTimeout ( 500 ) ;
80- }
74+ await dismissCookieConsent ( page ) ;
8175
8276 // Click "Create Integration" dropdown button (use .first() as there may be multiple)
8377 const createButton = page . getByRole ( 'button' , { name : 'Create Integration' } ) . first ( ) ;
@@ -91,58 +85,30 @@ test.describe('Webhook Integration Lifecycle', () => {
9185 await webhooksMenuItem . waitFor ( { state : 'visible' , timeout : 5000 } ) ;
9286 await webhooksMenuItem . click ( ) ;
9387
94- // Now the wizard dialog should open
95- await page . waitForTimeout ( 1000 ) ;
88+ // Wait for wizard dialog to open
89+ await page . waitForSelector ( '[role="dialog"]' , { state : 'visible' , timeout : 10000 } ) ;
9690
9791 // Fill the webhook form
9892 await fillWebhookForm ( page , webhookPayload ) ;
9993 await waitForSuccessNotification ( page ) ;
10094
101- // Modal closes automatically - wait for it
102- await page . waitForTimeout ( 2000 ) ;
95+ // Wait for modal to close
96+ await page . waitForSelector ( '[role="dialog"]' , { state : 'hidden' , timeout : 10000 } ) ;
10397
10498 // Navigate to Webhooks tab to verify the webhook appears
10599 const webhooksTab = page . locator ( 'button:has-text("Webhooks"), a:has-text("Webhooks")' ) . first ( ) ;
106100 await webhooksTab . click ( ) ;
107- await page . waitForLoadState ( 'networkidle' ) ;
108- await page . waitForTimeout ( 1000 ) ;
101+ await page . waitForLoadState ( 'domcontentloaded' ) ;
109102
110103 // Verify webhook appears in the list
111104 const webhookElement = page . locator ( `text="${ webhookPayload . name } "` ) . first ( ) ;
112105 await expect ( webhookElement ) . toBeVisible ( { timeout : 10000 } ) ;
113106
114107 // Delete the webhook
115- const container = page
116- . locator ( '[role="row"], [class*="card"]' , {
117- has : page . locator ( `text="${ webhookPayload . name } "` ) ,
118- } )
119- . first ( ) ;
120-
121- const deleteButton = container
122- . locator ( 'button[aria-label*="Delete"], button:has-text("Delete")' )
123- . first ( ) ;
124- if ( await deleteButton . isVisible ( { timeout : 3000 } ) . catch ( ( ) => false ) ) {
125- await deleteButton . click ( ) ;
126- } else {
127- const kebabButton = container
128- . locator ( 'button[aria-label*="Actions"], button[aria-label*="Kebab"]' )
129- . first ( ) ;
130- await kebabButton . click ( ) ;
131- await page . waitForTimeout ( 500 ) ;
132- const deleteMenuItem = page . locator ( 'button:has-text("Delete")' ) . first ( ) ;
133- await deleteMenuItem . click ( ) ;
134- }
135-
136- // Confirm deletion
137- const confirmButton = page
138- . locator ( 'button:has-text("Delete"), button:has-text("Confirm")' )
139- . first ( ) ;
140- await confirmButton . waitFor ( { state : 'visible' , timeout : 5000 } ) ;
141- await confirmButton . click ( { force : true } ) ;
108+ await deleteIntegration ( page , webhookPayload . name ) ;
142109
143- await page . waitForTimeout ( 2000 ) ;
144- const webhookGone = await webhookElement . isVisible ( { timeout : 2000 } ) . catch ( ( ) => false ) ;
145- expect ( webhookGone ) . toBe ( false ) ;
110+ // Verify it's gone
111+ await expect ( webhookElement ) . not . toBeVisible ( { timeout : 10000 } ) ;
146112 } ) ;
147113} ) ;
148114
@@ -156,16 +122,9 @@ test.describe('Communication Integration Lifecycle', () => {
156122
157123 // Navigate to integrations page
158124 await page . goto ( INTEGRATIONS_PATH ) ;
159- await page . waitForLoadState ( 'networkidle ' ) ;
125+ await page . waitForLoadState ( 'domcontentloaded ' ) ;
160126
161- // Dismiss cookie consent if it appears
162- const acceptCookies = page
163- . getByRole ( 'button' , { name : 'Accept all' } )
164- . or ( page . getByRole ( 'button' , { name : 'Accept' } ) ) ;
165- if ( await acceptCookies . isVisible ( { timeout : 2000 } ) . catch ( ( ) => false ) ) {
166- await acceptCookies . click ( ) ;
167- await page . waitForTimeout ( 500 ) ;
168- }
127+ await dismissCookieConsent ( page ) ;
169128
170129 // Click "Create Integration" dropdown button (same pattern as webhook)
171130 const createButton = page . getByRole ( 'button' , { name : 'Create Integration' } ) . first ( ) ;
@@ -179,61 +138,31 @@ test.describe('Communication Integration Lifecycle', () => {
179138 await communicationsMenuItem . waitFor ( { state : 'visible' , timeout : 5000 } ) ;
180139 await communicationsMenuItem . click ( ) ;
181140
182- // Wait for wizard to appear
183- await page . waitForTimeout ( 1000 ) ;
141+ // Wait for wizard dialog to open
142+ await page . waitForSelector ( '[role="dialog"]' , { state : 'visible' , timeout : 10000 } ) ;
184143
185- // Fill the communication form (wizard should be open now)
144+ // Fill the communication form
186145 await fillCommunicationForm ( page , payload ) ;
187146 await waitForSuccessNotification ( page ) ;
188147
189- // Modal closes automatically - wait for it
190- await page . waitForTimeout ( 2000 ) ;
148+ // Wait for modal to close
149+ await page . waitForSelector ( '[role="dialog"]' , { state : 'hidden' , timeout : 10000 } ) ;
191150
192151 // Navigate to Communications tab to verify the integration appears
193152 const communicationsTab = page
194153 . locator ( 'button:has-text("Communications"), a:has-text("Communications")' )
195154 . first ( ) ;
196155 await communicationsTab . click ( ) ;
197- await page . waitForLoadState ( 'networkidle' ) ;
198- await page . waitForTimeout ( 1000 ) ;
156+ await page . waitForLoadState ( 'domcontentloaded' ) ;
199157
200158 // Verify integration appears in the list
201159 const integrationElement = page . locator ( `text="${ payload . name } "` ) . first ( ) ;
202160 await expect ( integrationElement ) . toBeVisible ( { timeout : 10000 } ) ;
203161
204162 // Delete the integration
205- const container = page
206- . locator ( '[role="row"], [class*="card"]' , {
207- has : page . locator ( `text="${ payload . name } "` ) ,
208- } )
209- . first ( ) ;
163+ await deleteIntegration ( page , payload . name ) ;
210164
211- const deleteButton = container
212- . locator ( 'button[aria-label*="Delete"], button:has-text("Delete")' )
213- . first ( ) ;
214- if ( await deleteButton . isVisible ( { timeout : 3000 } ) . catch ( ( ) => false ) ) {
215- await deleteButton . click ( ) ;
216- } else {
217- const kebabButton = container
218- . locator ( 'button[aria-label*="Actions"], button[aria-label*="Kebab"]' )
219- . first ( ) ;
220- await kebabButton . click ( ) ;
221- await page . waitForTimeout ( 500 ) ;
222- const deleteMenuItem = page . locator ( 'button:has-text("Delete")' ) . first ( ) ;
223- await deleteMenuItem . click ( ) ;
224- }
225-
226- // Confirm deletion
227- const confirmButton = page
228- . locator ( 'button:has-text("Delete"), button:has-text("Confirm")' )
229- . first ( ) ;
230- await confirmButton . waitFor ( { state : 'visible' , timeout : 5000 } ) ;
231- await confirmButton . click ( { force : true } ) ;
232-
233- await page . waitForTimeout ( 2000 ) ;
234- const integrationGone = await integrationElement
235- . isVisible ( { timeout : 2000 } )
236- . catch ( ( ) => false ) ;
237- expect ( integrationGone ) . toBe ( false ) ;
165+ // Verify it's gone
166+ await expect ( integrationElement ) . not . toBeVisible ( { timeout : 10000 } ) ;
238167 } ) ;
239168} ) ;
0 commit comments