Skip to content

Commit 2868418

Browse files
authored
Improve E2E test reliability with better selectors and error handling (#76)
- Replace searchbox selectors with filter patterns for UI consistency - Add comprehensive error message surfacing in AppCatalogPage - Fix navigation reliability by scoping selectors to navigation context - Use exact matches for Fusion SOAR button to avoid content card conflicts - Handle dynamic button text with regex patterns (e.g., 'Endpoint security') - Remove waitForTimeout anti-patterns and unnecessary loader checks - Scope workflow menu buttons to specific rows to avoid conflicts These changes resolve selector ambiguity issues and improve test stability across different UI states and environments.
1 parent 8a9e905 commit 2868418

File tree

3 files changed

+28
-22
lines changed

3 files changed

+28
-22
lines changed

e2e/src/pages/AppCatalogPage.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ export class AppCatalogPage extends BasePage {
3333

3434
await this.navigateToPath('/foundry/app-catalog', 'App catalog page');
3535

36-
const searchBox = this.page.getByRole('searchbox', { name: 'Search' });
37-
await searchBox.fill(appName);
38-
await this.page.keyboard.press('Enter');
39-
await this.page.waitForLoadState('networkidle');
36+
const filterBox = this.page.getByPlaceholder('Type to filter');
37+
if (await filterBox.isVisible().catch(() => false)) {
38+
await filterBox.fill(appName);
39+
await this.page.waitForLoadState('networkidle');
40+
}
4041

4142
const appLink = this.page.getByRole('link', { name: appName, exact: true });
4243

@@ -220,15 +221,18 @@ export class AppCatalogPage extends BasePage {
220221
const errorMessage = this.page.getByText(`Error installing ${appName}`).first();
221222

222223
try {
223-
await Promise.race([
224+
const result = await Promise.race([
224225
installedMessage.waitFor({ state: 'visible', timeout: 60000 }).then(() => 'success'),
225226
errorMessage.waitFor({ state: 'visible', timeout: 60000 }).then(() => 'error')
226-
]).then(result => {
227-
if (result === 'error') {
228-
throw new Error(`Installation failed for app '${appName}' - error message appeared`);
229-
}
230-
this.logger.success('Installation completed successfully - "installed" message appeared');
231-
});
227+
]);
228+
229+
if (result === 'error') {
230+
// Get the actual error message from the toast and clean up formatting
231+
const errorText = await errorMessage.textContent();
232+
const cleanError = errorText?.replace(/\s+/g, ' ').trim() || 'Unknown error';
233+
throw new Error(`Installation failed for app '${appName}': ${cleanError}`);
234+
}
235+
this.logger.success('Installation completed successfully - "installed" message appeared');
232236
} catch (error) {
233237
if (error.message.includes('Installation failed')) {
234238
throw error;

e2e/src/pages/SocketNavigationPage.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,21 @@ export class SocketNavigationPage extends BasePage {
4242
await this.page.waitForLoadState('networkidle');
4343

4444
// Click "Endpoint security"
45-
const endpointSecurityButton = this.page.getByRole('button', { name: /Endpoint security/i });
45+
const navigation = this.page.getByRole('navigation');
46+
const endpointSecurityButton = navigation.getByRole('button', { name: /Endpoint security/ });
4647
await endpointSecurityButton.click();
4748
await this.waiter.delay(500);
4849

4950
// Click "Monitor" to expand submenu (if not already expanded)
50-
const monitorButton = this.page.getByRole('button', { name: /^Monitor$/i });
51+
const monitorButton = navigation.getByRole('button', { name: 'Monitor', exact: true });
5152
const isExpanded = await monitorButton.getAttribute('aria-expanded');
5253
if (isExpanded !== 'true') {
5354
await monitorButton.click();
5455
await this.waiter.delay(500);
5556
}
5657

5758
// Click "Endpoint detections" link
58-
const endpointDetectionsLink = this.page.getByRole('link', { name: /Endpoint detections/i });
59+
const endpointDetectionsLink = navigation.getByRole('link', { name: /Endpoint detections/ });
5960
await endpointDetectionsLink.click();
6061

6162
// Wait for page to load

e2e/src/pages/WorkflowsPage.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ export class WorkflowsPage extends BasePage {
3636
await menuButton.click();
3737
await this.page.waitForLoadState('networkidle');
3838

39-
// Click Fusion SOAR in the navigation menu (not the home page cards)
40-
const navigation = this.page.locator('nav, [role="navigation"]');
41-
const fusionSoarButton = navigation.getByRole('button', { name: 'Fusion SOAR' });
39+
// Click Fusion SOAR button in the navigation menu (not the content buttons)
40+
// Look for the navigation and find the exact "Fusion SOAR" button (not content that mentions Fusion SOAR)
41+
const navigation = this.page.getByRole('navigation');
42+
const fusionSoarButton = navigation.getByRole('button', { name: 'Fusion SOAR', exact: true });
4243
await fusionSoarButton.click();
43-
await this.page.waitForTimeout(500);
4444

4545
// Click Workflows link
4646
const workflowsLink = this.page.getByRole('link', { name: 'Workflows' });
@@ -161,11 +161,12 @@ export class WorkflowsPage extends BasePage {
161161
async () => {
162162
this.logger.info(`Executing workflow: ${workflowName}`);
163163

164-
// Open the workflow
165-
await this.openWorkflow(workflowName);
164+
// Ensure we're on the workflows list page, not an individual workflow page
165+
await this.navigateToWorkflows();
166166

167-
// Click "Open menu" button
168-
const openMenuButton = this.page.getByRole('button', { name: /open menu/i });
167+
// Click "Open menu" button for the specific workflow row
168+
const workflowRow = this.page.getByRole('row', { name: new RegExp(workflowName, 'i') });
169+
const openMenuButton = workflowRow.getByRole('button', { name: /open menu/i });
169170
await openMenuButton.click();
170171

171172
// Click "Execute workflow" option

0 commit comments

Comments
 (0)