Files
bruno/tests/utils/page/runner.ts
naman-bruno e93e545b81 improve: tests (#6321)
* improve: tests

* fixes

* fixes
2025-12-06 15:36:58 +05:30

189 lines
8.1 KiB
TypeScript

import { Page, expect, test } from '../../../playwright';
/**
* Builds locators for the runner results view
* @param page - The Playwright page object
* @returns Object with locators for runner elements
*/
export const buildRunnerLocators = (page: Page) => ({
allButton: () => page.locator('button').filter({ hasText: /^All/ }),
passedButton: () => page.locator('button').filter({ hasText: /^Passed/ }),
failedButton: () => page.locator('button').filter({ hasText: /^Failed/ }),
skippedButton: () => page.locator('button').filter({ hasText: /^Skipped/ }),
resetButton: () => page.getByRole('button', { name: 'Reset' }),
runCollectionButton: () => page.getByRole('button', { name: 'Run Collection' }),
runAgainButton: () => page.getByRole('button', { name: 'Run Again' })
});
/**
* Reads test result counts from the filter buttons in the runner results view
* @param page - The Playwright page object
* @returns An object with totalRequests, passed, failed, and skipped counts
*/
export const getRunnerResultCounts = async (page: Page) => {
const locators = buildRunnerLocators(page);
const totalRequests = parseInt(await locators.allButton().locator('span').innerText());
const passed = parseInt(await locators.passedButton().locator('span').innerText());
const failed = parseInt(await locators.failedButton().locator('span').innerText());
const skipped = parseInt(await locators.skippedButton().locator('span').innerText());
return { totalRequests, passed, failed, skipped };
};
/**
* Runs a collection by clicking the Run menu item and handling the runner tab
* Includes logic to reset existing results if present
* @param page - The Playwright page object
* @param collectionName - The name of the collection to run
* @returns void
*/
export const runCollection = async (page: Page, collectionName: string) => {
await test.step(`Run collection "${collectionName}"`, async () => {
// Ensure collection is visible and loaded (scope to sidebar)
const collectionContainer = page.getByTestId('collections').locator('.collection-name').filter({ hasText: collectionName });
await collectionContainer.waitFor({ state: 'visible' });
// Open collection actions menu - wait for the actions container to be actionable
const actionsContainer = collectionContainer.locator('.collection-actions');
await actionsContainer.waitFor({ state: 'visible' });
await actionsContainer.hover();
const icon = actionsContainer.locator('.icon');
await icon.waitFor({ state: 'visible', timeout: 5000 });
await icon.click();
// Click Run menu item
const runMenuItem = page.getByText('Run', { exact: true });
await runMenuItem.waitFor({ state: 'visible' });
await runMenuItem.click();
// Handle runner tab - reset if needed, then run
const locators = buildRunnerLocators(page);
// Check if Reset button is visible (means there are existing results)
const resetVisible = await locators.resetButton().isVisible({ timeout: 1000 }).catch(() => false);
if (resetVisible) {
await locators.resetButton().click();
// Wait for the Run Collection button to become visible after reset
await locators.runCollectionButton().waitFor({ state: 'visible', timeout: 5000 });
}
// Now wait for and click Run Collection button
await locators.runCollectionButton().waitFor({ state: 'visible', timeout: 10000 });
await locators.runCollectionButton().click();
// Wait for the run to complete
await locators.runAgainButton().waitFor({ timeout: 2 * 60 * 1000 });
});
};
/**
* Builds locators for sandbox mode settings
* @param page - The Playwright page object
* @returns Object with locators for sandbox elements
*/
export const buildSandboxLocators = (page: Page) => ({
developerModeBadge: () => page.locator('.developer-mode').filter({ hasText: 'Developer Mode' }),
safeModeBadge: () => page.locator('.safe-mode').filter({ hasText: 'Safe Mode' }),
safeModeRadio: () => page.getByLabel('Safe Mode'),
developerModeRadio: () => page.getByLabel('Developer Mode(use only if'),
jsSandboxHeading: () => page.getByText('JavaScript Sandbox'),
saveButton: () => page.getByRole('button', { name: 'Save' })
});
/**
* Sets up the JavaScript sandbox mode for a collection
* @param page - The Playwright page object
* @param collectionName - The name of the collection (can be title or text)
* @param mode - 'developer' or 'safe' mode
* @returns void
*/
export const setSandboxMode = async (page: Page, collectionName: string, mode: 'developer' | 'safe') => {
await test.step(`Set sandbox mode to "${mode}" for "${collectionName}"`, async () => {
const sandboxLocators = buildSandboxLocators(page);
// Click on the collection name in the sidebar
const sidebarCollection = page.getByTestId('collections').locator('#sidebar-collection-name').filter({ hasText: collectionName }).first();
await sidebarCollection.waitFor({ state: 'visible' });
await sidebarCollection.click();
// Check if there's already a mode selected - if so, we need to click the badge to open settings tab
const developerBadgeVisible = await sandboxLocators.developerModeBadge().isVisible().catch(() => false);
const safeBadgeVisible = await sandboxLocators.safeModeBadge().isVisible().catch(() => false);
// If a badge exists, click it to open the security settings tab
if (developerBadgeVisible || safeBadgeVisible) {
if (developerBadgeVisible) {
await sandboxLocators.developerModeBadge().click();
} else {
await sandboxLocators.safeModeBadge().click();
}
// Wait for the security settings tab to be active
await sandboxLocators.jsSandboxHeading().waitFor({ state: 'visible', timeout: 10000 });
}
// If no badge exists, the modal should have appeared automatically (first time selection)
// Wait for security settings form to be visible - wait for either radio button
await Promise.race([
sandboxLocators.safeModeRadio().waitFor({ state: 'visible', timeout: 10000 }).catch(() => {}),
sandboxLocators.developerModeRadio().waitFor({ state: 'visible', timeout: 10000 }).catch(() => {})
]);
if (mode === 'developer') {
await sandboxLocators.developerModeRadio().waitFor({ state: 'visible', timeout: 5000 });
await sandboxLocators.developerModeRadio().check();
} else {
// For safe mode, check if developer mode is currently selected
const developerModeChecked = await sandboxLocators.developerModeRadio().isChecked().catch(() => false);
if (developerModeChecked) {
// Click the Developer Mode label text inside the security settings form
const securityForm = page.locator('div').filter({ hasText: 'JavaScript Sandbox' }).locator('..').first();
const developerLabel = securityForm.locator('label').filter({ hasText: /^Developer Mode/ }).first();
await developerLabel.waitFor({ state: 'visible', timeout: 5000 });
await developerLabel.click();
}
// Ensure Safe Mode radio is visible and check it
await sandboxLocators.safeModeRadio().waitFor({ state: 'visible', timeout: 5000 });
await sandboxLocators.safeModeRadio().check();
}
await sandboxLocators.saveButton().click();
});
};
/**
* Validates runner results against expected counts
* @param page - The Playwright page object
* @param expected - Expected counts
* @returns void
*/
export const validateRunnerResults = async (page: Page,
expected: {
totalRequests?: number;
passed?: number;
failed?: number;
skipped?: number;
}) => {
const { totalRequests, passed, failed, skipped } = await getRunnerResultCounts(page);
if (expected.totalRequests !== undefined) {
await expect(totalRequests).toBe(expected.totalRequests);
}
if (expected.passed !== undefined) {
await expect(passed).toBe(expected.passed);
}
if (expected.failed !== undefined) {
await expect(failed).toBe(expected.failed);
}
if (expected.skipped !== undefined) {
await expect(skipped).toBe(expected.skipped);
}
// Validate that passed + failed + skipped = totalRequests
await expect(passed).toBe(totalRequests - skipped - failed);
};