From 45cfbc5c499cdd2344380238ceea9393c4dc7316 Mon Sep 17 00:00:00 2001 From: morgan-se Date: Wed, 12 Nov 2025 21:18:31 +1300 Subject: [PATCH 1/5] Moved collection results to runner title bar so they are move visible. (#3808) Added breakdown of test results within collection. Added filtering based on passing/failing requests and tests by click on results text. Co-authored-by: Morgan English Co-authored-by: Sid --- .../src/components/RunnerResults/index.jsx | 72 +++++++++++++++++-- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/packages/bruno-app/src/components/RunnerResults/index.jsx b/packages/bruno-app/src/components/RunnerResults/index.jsx index 7956eb1ad..31b6d97f2 100644 --- a/packages/bruno-app/src/components/RunnerResults/index.jsx +++ b/packages/bruno-app/src/components/RunnerResults/index.jsx @@ -46,6 +46,24 @@ export default function RunnerResults({ collection }) { const dispatch = useDispatch(); const [selectedItem, setSelectedItem] = useState(null); const [delay, setDelay] = useState(null); + const [activeFilter, setActiveFilter] = useState('all'); + + + const getActiveFilterPredicate = () => { + switch (activeFilter) { + case 'passing_requests': + return (item) => item.status !== 'error' && item.testStatus === 'pass' && item.assertionStatus === 'pass'; + case 'failing_requests': + return (item) => (item.status !== 'error' && item.testStatus === 'fail') || item.assertionStatus === 'fail'; + case 'passing_tests': + return (item) => item.testResults?.some((result) => result.status === 'pass'); + case 'failing_tests': + return (item) => item.testResults?.some((result) => result.status === 'fail' || result.status === 'error'); + default: + return () => true + } + } + const [selectedRequestItems, setSelectedRequestItems] = useState([]); const [configureMode, setConfigureMode] = useState(false); @@ -192,6 +210,44 @@ export default function RunnerResults({ collection }) { }, [tagsEnabled]); const totalRequestsInCollection = getTotalRequestCountInCollection(collectionCopy); + + const displayCollectionResults = () => { + let passedRequests = 0; + let failedRequests = 0; + let totalTestsInCollection = 0; + let passedTests = 0; + let failedTests = 0; + items.forEach(item => { + const isPassedRequest = item.status !== 'error' && item.testStatus === 'pass' && item.assertionStatus === 'pass'; + const isFailedRequest = (item.status !== 'error' && item.testStatus === 'fail') || item.assertionStatus === 'fail'; + + if (isPassedRequest) passedRequests++; + if (isFailedRequest) failedRequests++; + + const testResults = Array.isArray(item?.testResults) ? item.testResults : []; + totalTestsInCollection += testResults.length; + testResults.forEach(result => { + if (result.status === 'pass') passedTests++; + if (result.status === 'fail' || result.status === 'error') failedTests++; + }); + }); + + return ( +
+
+ setActiveFilter('all')} className={`cursor-pointer ${activeFilter === 'all' ? 'underline font-semibold' : ''} hover:font-semibold`}>Total Requests: {items.length}, + setActiveFilter('passing_requests')} className={`cursor-pointer ${activeFilter === 'passing_requests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Passed: {passedRequests}, + setActiveFilter('failing_requests') } className={`cursor-pointer ${activeFilter === 'failing_requests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Failed: {failedRequests} +
+
+ setActiveFilter('all')} className={`cursor-pointer ${activeFilter === 'all' ? 'underline font-semibold' : ''} hover:font-semibold`}>Total Tests: {totalTestsInCollection}, + setActiveFilter('passing_tests')} className={`cursor-pointer ${activeFilter === 'passing_tests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Passed: {passedTests}, + setActiveFilter('failing_tests')} className={`cursor-pointer ${activeFilter === 'failing_tests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Failed: {failedTests} +
+
+ ) + } + const passedRequests = items.filter(allTestsPassed); const failedRequests = items.filter(anyTestFailed); @@ -290,6 +346,7 @@ export default function RunnerResults({ collection }) { Runner + {displayCollectionResults()} {runnerInfo.status !== 'ended' && runnerInfo.cancelTokenUid && ( +); + export default function RunnerResults({ collection }) { const dispatch = useDispatch(); const [selectedItem, setSelectedItem] = useState(null); const [delay, setDelay] = useState(null); const [activeFilter, setActiveFilter] = useState('all'); - - - const getActiveFilterPredicate = () => { - switch (activeFilter) { - case 'passing_requests': - return (item) => item.status !== 'error' && item.testStatus === 'pass' && item.assertionStatus === 'pass'; - case 'failing_requests': - return (item) => (item.status !== 'error' && item.testStatus === 'fail') || item.assertionStatus === 'fail'; - case 'passing_tests': - return (item) => item.testResults?.some((result) => result.status === 'pass'); - case 'failing_tests': - return (item) => item.testResults?.some((result) => result.status === 'fail' || result.status === 'error'); - default: - return () => true - } - } - const [selectedRequestItems, setSelectedRequestItems] = useState([]); const [configureMode, setConfigureMode] = useState(false); - // ref for the runner output body const runnerBodyRef = useRef(); - const autoScrollRunnerBody = () => { - if (runnerBodyRef?.current) { - // mimics the native terminal scroll style - runnerBodyRef.current.scrollTo(0, 100000); - } - }; - - useEffect(() => { - if (!collection.runnerResult) { - setSelectedItem(null); - } - autoScrollRunnerBody(); - }, [collection, setSelectedItem]); - - useEffect(() => { - const runnerInfo = get(collection, 'runnerResult.info', {}); - if (runnerInfo.status === 'running') { - setConfigureMode(false); - } - }, [collection.runnerResult]); - - useEffect(() => { - const savedConfiguration = get(collection, 'runnerConfiguration', null); - if (savedConfiguration) { - if (savedConfiguration.selectedRequestItems && configureMode) { - setSelectedRequestItems(savedConfiguration.selectedRequestItems); - } - if (savedConfiguration.delay !== undefined && delay === null) { - setDelay(savedConfiguration.delay); - } - } - }, [collection.runnerConfiguration, configureMode, delay]); - const collectionCopy = cloneDeep(collection); const runnerInfo = get(collection, 'runnerResult.info', {}); @@ -144,6 +135,63 @@ export default function RunnerResults({ collection }) { }) .filter(Boolean); + const activeFilterConfig = FILTERS[activeFilter]; + const filteredItems = items.filter(activeFilterConfig.predicate); + + const filterTestResults = (results) => { + if (!results || !Array.isArray(results)) return []; + return activeFilterConfig.resultFilter(results); + }; + + const autoScrollRunnerBody = () => { + if (runnerBodyRef?.current) { + const element = runnerBodyRef.current; + const scrollThreshold = 100; // pixels from bottom to consider "at bottom" + const isNearBottom + = element.scrollHeight - element.scrollTop - element.clientHeight < scrollThreshold; + + // Only auto-scroll if user is already near the bottom + if (isNearBottom) { + // mimics the native terminal scroll style + element.scrollTo(0, 100000); + } + } + }; + + useEffect(() => { + if (!collection.runnerResult) { + setSelectedItem(null); + } + autoScrollRunnerBody(); + }, [collection, setSelectedItem]); + + useEffect(() => { + // Auto-scroll when items are added or updated during execution + // Only scrolls if user is already at/near the bottom + if (filteredItems.length > 0) { + autoScrollRunnerBody(); + } + }, [filteredItems]); + + useEffect(() => { + const runnerInfo = get(collection, 'runnerResult.info', {}); + if (runnerInfo.status === 'running') { + setConfigureMode(false); + } + }, [collection.runnerResult]); + + useEffect(() => { + const savedConfiguration = get(collection, 'runnerConfiguration', null); + if (savedConfiguration) { + if (savedConfiguration.selectedRequestItems && configureMode) { + setSelectedRequestItems(savedConfiguration.selectedRequestItems); + } + if (savedConfiguration.delay !== undefined && delay === null) { + setDelay(savedConfiguration.delay); + } + } + }, [collection.runnerConfiguration, configureMode, delay]); + const ensureCollectionIsMounted = () => { if(collection.mountStatus === 'mounted'){ return; @@ -210,52 +258,14 @@ export default function RunnerResults({ collection }) { }, [tagsEnabled]); const totalRequestsInCollection = getTotalRequestCountInCollection(collectionCopy); + const filterCounts = { + all: items.length, + passed: items.filter(allTestsPassed).length, + failed: items.filter(anyTestFailed).length, + skipped: items.filter((i) => i.status === 'skipped').length + }; - const displayCollectionResults = () => { - let passedRequests = 0; - let failedRequests = 0; - let totalTestsInCollection = 0; - let passedTests = 0; - let failedTests = 0; - items.forEach(item => { - const isPassedRequest = item.status !== 'error' && item.testStatus === 'pass' && item.assertionStatus === 'pass'; - const isFailedRequest = (item.status !== 'error' && item.testStatus === 'fail') || item.assertionStatus === 'fail'; - - if (isPassedRequest) passedRequests++; - if (isFailedRequest) failedRequests++; - - const testResults = Array.isArray(item?.testResults) ? item.testResults : []; - totalTestsInCollection += testResults.length; - testResults.forEach(result => { - if (result.status === 'pass') passedTests++; - if (result.status === 'fail' || result.status === 'error') failedTests++; - }); - }); - - return ( -
-
- setActiveFilter('all')} className={`cursor-pointer ${activeFilter === 'all' ? 'underline font-semibold' : ''} hover:font-semibold`}>Total Requests: {items.length}, - setActiveFilter('passing_requests')} className={`cursor-pointer ${activeFilter === 'passing_requests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Passed: {passedRequests}, - setActiveFilter('failing_requests') } className={`cursor-pointer ${activeFilter === 'failing_requests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Failed: {failedRequests} -
-
- setActiveFilter('all')} className={`cursor-pointer ${activeFilter === 'all' ? 'underline font-semibold' : ''} hover:font-semibold`}>Total Tests: {totalTestsInCollection}, - setActiveFilter('passing_tests')} className={`cursor-pointer ${activeFilter === 'passing_tests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Passed: {passedTests}, - setActiveFilter('failing_tests')} className={`cursor-pointer ${activeFilter === 'failing_tests' ? 'underline font-semibold' : ''} hover:font-semibold`}>Failed: {failedTests} -
-
- ) - } - - const passedRequests = items.filter(allTestsPassed); - const failedRequests = items.filter(anyTestFailed); - - const skippedRequests = items.filter((item) => { - return item.status === 'skipped'; - }); let isCollectionLoading = areItemsLoading(collection); - if (!items || !items.length) { return ( @@ -341,35 +351,57 @@ export default function RunnerResults({ collection }) { return ( -
-
- Runner - + {/* Filter Bar and Actions */} +
+
+
+ + Filter by: + +
+
+ {Object.entries(FILTERS).map(([key, { label }]) => ( + setActiveFilter(key)} + /> + ))} +
- {displayCollectionResults()} - {runnerInfo.status !== 'ended' && runnerInfo.cancelTokenUid && ( - - )} + + {runnerInfo.status !== 'ended' && runnerInfo.cancelTokenUid ? ( +
+ +
+ ) : runnerInfo.status === 'ended' ? ( +
+ + +
+ ) : null}
- {runnerInfo?.statusText ? -
- {runnerInfo?.statusText} -
- : null} - -
- Total Requests: {items.length}, Passed: {passedRequests.length}, Failed: {failedRequests.length}, Skipped:{' '} - {skippedRequests.length} -
- {tagsEnabled && areTagsAdded && (
Tags: @@ -383,9 +415,15 @@ export default function RunnerResults({ collection }) {
)} + {runnerInfo?.statusText ? +
+ {runnerInfo?.statusText} +
+ : null} + {/* Items list */} -
- {items.filter(getActiveFilterPredicate()).map((item) => { +
+ {filteredItems.map((item) => { return (
@@ -429,7 +467,7 @@ export default function RunnerResults({ collection }) {
    {item.preRequestTestResults - ? item.preRequestTestResults.map((result) => ( + ? filterTestResults(item.preRequestTestResults).map((result) => (
  • {result.status === 'pass' ? ( @@ -449,7 +487,7 @@ export default function RunnerResults({ collection }) { )) : null} {item.postResponseTestResults - ? item.postResponseTestResults.map((result) => ( + ? filterTestResults(item.postResponseTestResults).map((result) => (
  • {result.status === 'pass' ? ( @@ -469,7 +507,7 @@ export default function RunnerResults({ collection }) { )) : null} {item.testResults - ? item.testResults.map((result) => ( + ? filterTestResults(item.testResults).map((result) => (
  • {result.status === 'pass' ? ( @@ -488,7 +526,7 @@ export default function RunnerResults({ collection }) {
  • )) : null} - {item.assertionResults?.map((result) => ( + {filterTestResults(item.assertionResults).map((result) => (
  • {result.status === 'pass' ? ( @@ -512,43 +550,51 @@ export default function RunnerResults({ collection }) { ); })}
- - {runnerInfo.status === 'ended' ? ( -
- - - -
- ) : null}
+ {selectedItem ? (
-
- {selectedItem.displayName} - - {allTestsPassed(selectedItem) ? - - : null} - {anyTestFailed(selectedItem) ? - - : null} - {selectedItem.status === 'skipped' ? - - : null} - +
+
+ {selectedItem.displayName} + + {allTestsPassed(selectedItem) + ? + : null} + {anyTestFailed(selectedItem) + ? + : null} + {selectedItem.status === 'skipped' + ? + : null} + +
+
- ) : null} + ) : ( +
+
+
+ +
+

+ Click on the status code to view the response +

+
+
+ )}
); -} +} \ No newline at end of file From 6628f95677943c7032c30dd463d746a4124afad8 Mon Sep 17 00:00:00 2001 From: Sid Date: Wed, 12 Nov 2025 14:15:06 +0530 Subject: [PATCH 3/5] fix: add missing newline at end of file in RunnerResults component --- packages/bruno-app/src/components/RunnerResults/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/RunnerResults/index.jsx b/packages/bruno-app/src/components/RunnerResults/index.jsx index 8ce7b945f..ba6521be5 100644 --- a/packages/bruno-app/src/components/RunnerResults/index.jsx +++ b/packages/bruno-app/src/components/RunnerResults/index.jsx @@ -597,4 +597,4 @@ export default function RunnerResults({ collection }) {
); -} \ No newline at end of file +} From 6049530634d5959e14e7b3a1399772ff6c51c806 Mon Sep 17 00:00:00 2001 From: Chirag Chandrashekhar Date: Thu, 13 Nov 2025 15:56:33 +0530 Subject: [PATCH 4/5] refactor: update runner tests to use new filter implementation and reusable helpers (#6085) --- .../src/components/RunnerResults/index.jsx | 2 +- tests/runner/collection-run.ts | 68 ++++--- .../jsonwebtoken/jsonwebtoken.spec.ts | 72 +++---- .../basic-ssl-success.spec.ts | 73 +++---- .../self-signed-rejected.spec.ts | 71 +++---- ...d-success-with-validation-disabled.spec.ts | 73 +++---- ...id-ca-cert-in-config-with-defaults.spec.ts | 73 +++---- .../custom-invalid-ca-cert-in-config.spec.ts | 73 +++---- ...id-ca-cert-in-config-with-defaults.spec.ts | 75 +++---- .../custom-valid-ca-cert-in-config.spec.ts | 75 +++---- tests/utils/page/index.ts | 1 + tests/utils/page/runner.ts | 191 ++++++++++++++++++ 12 files changed, 457 insertions(+), 390 deletions(-) create mode 100644 tests/utils/page/runner.ts diff --git a/packages/bruno-app/src/components/RunnerResults/index.jsx b/packages/bruno-app/src/components/RunnerResults/index.jsx index ba6521be5..8ce7b945f 100644 --- a/packages/bruno-app/src/components/RunnerResults/index.jsx +++ b/packages/bruno-app/src/components/RunnerResults/index.jsx @@ -597,4 +597,4 @@ export default function RunnerResults({ collection }) {
); -} +} \ No newline at end of file diff --git a/tests/runner/collection-run.ts b/tests/runner/collection-run.ts index d683712de..8ac19857c 100644 --- a/tests/runner/collection-run.ts +++ b/tests/runner/collection-run.ts @@ -1,27 +1,24 @@ -import { test, expect } from '../../playwright'; +import { test } from '../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../utils/page/index'; test.describe.parallel('Collection Run', () => { test('Run bruno-testbench in Developer Mode', async ({ pageWithUserData: page }) => { test.setTimeout(2 * 60 * 1000); - await page.getByText('bruno-testbench').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); + // Set up developer mode + await setSandboxMode(page, 'bruno-testbench', 'developer'); + + // Select environment await page.locator('.environment-selector').nth(1).click(); await page.locator('.dropdown-item').getByText('Prod').click(); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const [totalRequests, passed, failed, skipped] = result - .match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/) - .slice(1); + // Run the collection + await runCollection(page, 'bruno-testbench'); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Validate test results + await validateRunnerResults(page, { + failed: 0 + }); }); test.fixme('Run bruno-testbench in Safe Mode', async ({ pageWithUserData: page }) => { @@ -32,18 +29,41 @@ test.describe.parallel('Collection Run', () => { await page.getByRole('button', { name: 'Save' }).click(); await page.locator('.environment-selector').nth(1).click(); await page.locator('.dropdown-item').getByText('Prod').click(); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); + const collectionContainer = page.locator('.collection-name').filter({ hasText: 'bruno-testbench' }); + await collectionContainer.locator('.collection-actions').hover(); + await collectionContainer.locator('.collection-actions .icon').waitFor({ state: 'visible' }); + await collectionContainer.locator('.collection-actions .icon').click(); await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); + // Wait for the runner tab to open + // If there are existing results, reset first, otherwise wait for Run Collection button + const resetButton = page.getByRole('button', { name: 'Reset' }); + const runCollectionButton = page.getByRole('button', { name: 'Run Collection' }); + + // Check if Reset button is visible (means there are existing results) + const resetVisible = await resetButton.isVisible().catch(() => false); + if (resetVisible) { + await resetButton.click(); + // Wait a bit for the reset to complete + await page.waitForTimeout(500); + } + + // Now wait for and click Run Collection button + await runCollectionButton.waitFor({ state: 'visible', timeout: 10000 }); + await runCollectionButton.click(); await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const [totalRequests, passed, failed, skipped] = result - .match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/) - .slice(1); + // Parse and validate test results from filter buttons + const allButton = page.locator('button').filter({ hasText: /^All/ }); + const passedButton = page.locator('button').filter({ hasText: /^Passed/ }); + const failedButton = page.locator('button').filter({ hasText: /^Failed/ }); + const skippedButton = page.locator('button').filter({ hasText: /^Skipped/ }); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + const totalRequests = parseInt(await allButton.locator('span').innerText()); + const passed = parseInt(await passedButton.locator('span').innerText()); + const failed = parseInt(await failedButton.locator('span').innerText()); + const skipped = parseInt(await skippedButton.locator('span').innerText()); + + await expect(failed).toBe(0); + await expect(passed).toBe(totalRequests - skipped - failed); }); }); \ No newline at end of file diff --git a/tests/scripting/inbuilt-libraries/jsonwebtoken/jsonwebtoken.spec.ts b/tests/scripting/inbuilt-libraries/jsonwebtoken/jsonwebtoken.spec.ts index 74bb23c6d..dacdf563b 100644 --- a/tests/scripting/inbuilt-libraries/jsonwebtoken/jsonwebtoken.spec.ts +++ b/tests/scripting/inbuilt-libraries/jsonwebtoken/jsonwebtoken.spec.ts @@ -1,64 +1,40 @@ -import { test, expect } from '../../../../playwright'; +import { test } from '../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../utils/page'; test.describe.serial('jwt collection success', () => { test('developer mode', async ({ pageWithUserData: page }) => { - // init dev mode - await page.getByTitle('jsonwebtoken').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); + // Set up developer mode + await setSandboxMode(page, 'jsonwebtoken', 'developer'); + // Run the collection - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); + await runCollection(page, 'jsonwebtoken'); - // Parse and validate test results - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - - await expect(parseInt(totalRequests)).toBe(7); - await expect(parseInt(passed)).toBe(7); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Validate test results + await validateRunnerResults(page, { + totalRequests: 7, + passed: 7, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - // init safe mode - await page.getByTitle('jsonwebtoken').click(); - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); + // Set up safe mode + await setSandboxMode(page, 'jsonwebtoken', 'safe'); + // Run the collection - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); + await runCollection(page, 'jsonwebtoken'); - // Parse and validate test results - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - - await expect(parseInt(totalRequests)).toBe(7); - await expect(parseInt(passed)).toBe(7); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Validate test results + await validateRunnerResults(page, { + totalRequests: 7, + passed: 7, + failed: 0, + skipped: 0 + }); }); }); diff --git a/tests/ssl/basic-ssl/tests/basic-ssl-success/basic-ssl-success.spec.ts b/tests/ssl/basic-ssl/tests/basic-ssl-success/basic-ssl-success.spec.ts index 26eb6bf2f..85131cee3 100644 --- a/tests/ssl/basic-ssl/tests/basic-ssl-success/basic-ssl-success.spec.ts +++ b/tests/ssl/basic-ssl/tests/basic-ssl-success/basic-ssl-success.spec.ts @@ -1,59 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; test.describe.serial('basic ssl success', () => { test('developer mode', async ({ pageWithUserData: page }) => { - - // init dev mode - await page.getByText('badssl').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'badssl', 'developer'); + + // Run the collection + await runCollection(page, 'badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); + // Set up safe mode + await setSandboxMode(page, 'badssl', 'safe'); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Run the collection + await runCollection(page, 'badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/basic-ssl/tests/self-signed-rejected/self-signed-rejected.spec.ts b/tests/ssl/basic-ssl/tests/self-signed-rejected/self-signed-rejected.spec.ts index 0674154a4..489177144 100644 --- a/tests/ssl/basic-ssl/tests/self-signed-rejected/self-signed-rejected.spec.ts +++ b/tests/ssl/basic-ssl/tests/self-signed-rejected/self-signed-rejected.spec.ts @@ -1,57 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; test.describe.serial('self signed rejected', () => { test('developer mode', async ({ pageWithUserData: page }) => { - // init dev mode - await page.getByText('self-signed-badssl').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(0); - await expect(parseInt(failed)).toBe(1); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'self-signed-badssl', 'developer'); + + // Run the collection + await runCollection(page, 'self-signed-badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 0, + failed: 1, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); + // Set up safe mode + await setSandboxMode(page, 'self-signed-badssl', 'safe'); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(0); - await expect(parseInt(failed)).toBe(1); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Run the collection + await runCollection(page, 'self-signed-badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 0, + failed: 1, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/basic-ssl/tests/self-signed-success-with-validation-disabled/self-signed-success-with-validation-disabled.spec.ts b/tests/ssl/basic-ssl/tests/self-signed-success-with-validation-disabled/self-signed-success-with-validation-disabled.spec.ts index d8edf5a0a..4b2543db8 100644 --- a/tests/ssl/basic-ssl/tests/self-signed-success-with-validation-disabled/self-signed-success-with-validation-disabled.spec.ts +++ b/tests/ssl/basic-ssl/tests/self-signed-success-with-validation-disabled/self-signed-success-with-validation-disabled.spec.ts @@ -1,59 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; test.describe.serial('self signed success with validation disabled', () => { test('developer mode', async ({ pageWithUserData: page }) => { - - // init dev mode - await page.getByText('self-signed-badssl').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'self-signed-badssl', 'developer'); + + // Run the collection + await runCollection(page, 'self-signed-badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); + // Set up safe mode + await setSandboxMode(page, 'self-signed-badssl', 'safe'); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Run the collection + await runCollection(page, 'self-signed-badssl'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config-with-defaults/custom-invalid-ca-cert-in-config-with-defaults.spec.ts b/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config-with-defaults/custom-invalid-ca-cert-in-config-with-defaults.spec.ts index 7b43ead19..b34314214 100644 --- a/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config-with-defaults/custom-invalid-ca-cert-in-config-with-defaults.spec.ts +++ b/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config-with-defaults/custom-invalid-ca-cert-in-config-with-defaults.spec.ts @@ -1,55 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; -test.describe.serial('custom invalid ca cert added to the config and keep default ca certs', () => { +test.describe('custom invalid ca cert added to the config and keep default ca certs', () => { test('developer mode', async ({ pageWithUserData: page }) => { - // init dev mode - await page.getByText('custom-ca-certs').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'custom-ca-certs', 'developer'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up safe mode + await setSandboxMode(page, 'custom-ca-certs', 'safe'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config/custom-invalid-ca-cert-in-config.spec.ts b/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config/custom-invalid-ca-cert-in-config.spec.ts index 9d89e0bc4..825bcc63c 100644 --- a/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config/custom-invalid-ca-cert-in-config.spec.ts +++ b/tests/ssl/custom-ca-certs/tests/custom-invalid-ca-cert-in-config/custom-invalid-ca-cert-in-config.spec.ts @@ -1,57 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; test.describe.serial('custom invalid ca cert added to the config and NO default ca certs', () => { test('developer mode', async ({ pageWithUserData: page }) => { - - // init dev mode - await page.getByText('custom-ca-certs').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(0); - await expect(parseInt(failed)).toBe(1); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'custom-ca-certs', 'developer'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 0, + failed: 1, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(0); - await expect(parseInt(failed)).toBe(1); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up safe mode + await setSandboxMode(page, 'custom-ca-certs', 'safe'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 0, + failed: 1, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config-with-defaults/custom-valid-ca-cert-in-config-with-defaults.spec.ts b/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config-with-defaults/custom-valid-ca-cert-in-config-with-defaults.spec.ts index 97db83b44..3811355c4 100644 --- a/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config-with-defaults/custom-valid-ca-cert-in-config-with-defaults.spec.ts +++ b/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config-with-defaults/custom-valid-ca-cert-in-config-with-defaults.spec.ts @@ -1,57 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; -test.describe.serial('custom valid ca cert added to the config and keep default ca certs', () => { +test.describe('custom valid ca cert added to the config and keep default ca certs', () => { test('developer mode', async ({ pageWithUserData: page }) => { - - // init dev mode - await page.getByText('custom-ca-certs').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'custom-ca-certs', 'developer'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up safe mode + await setSandboxMode(page, 'custom-ca-certs', 'safe'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config/custom-valid-ca-cert-in-config.spec.ts b/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config/custom-valid-ca-cert-in-config.spec.ts index 35a7776b2..603976275 100644 --- a/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config/custom-valid-ca-cert-in-config.spec.ts +++ b/tests/ssl/custom-ca-certs/tests/custom-valid-ca-cert-in-config/custom-valid-ca-cert-in-config.spec.ts @@ -1,57 +1,40 @@ -import { test, expect } from '../../../../../playwright'; +import { test } from '../../../../../playwright'; +import { setSandboxMode, runCollection, validateRunnerResults } from '../../../../utils/page'; -test.describe.serial('custom valid ca cert added to the config and NO default ca certs', () => { +test.describe('custom valid ca cert added to the config and NO default ca certs', () => { test('developer mode', async ({ pageWithUserData: page }) => { - - // init dev mode - await page.getByText('custom-ca-certs').click(); - await page.getByLabel('Developer Mode(use only if').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up developer mode + await setSandboxMode(page, 'custom-ca-certs', 'developer'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); test('safe mode', async ({ pageWithUserData: page }) => { - - // init safe mode - await page.getByText('Developer Mode').click(); - await page.getByLabel('Safe Mode').check(); - await page.getByRole('button', { name: 'Save' }).click(); - test.setTimeout(2 * 60 * 1000); - await page.locator('.collection-actions').hover(); - await page.locator('.collection-actions .icon').click(); - await page.getByText('Run', { exact: true }).click(); - await page.getByRole('button', { name: 'Run Collection' }).click(); - await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); - const result = await page.getByText('Total Requests: ').innerText(); - const matches = result.match(/Total Requests: (\d+), Passed: (\d+), Failed: (\d+), Skipped: (\d+)/); - if (!matches) { - throw new Error('Could not parse test results'); - } - const [totalRequests, passed, failed, skipped] = matches.slice(1); - await expect(parseInt(totalRequests)).toBe(1); - await expect(parseInt(passed)).toBe(1); - await expect(parseInt(failed)).toBe(0); - await expect(parseInt(skipped)).toBe(0); - await expect(parseInt(passed)).toBe(parseInt(totalRequests) - parseInt(skipped) - parseInt(failed)); + // Set up safe mode + await setSandboxMode(page, 'custom-ca-certs', 'safe'); + + // Run the collection + await runCollection(page, 'custom-ca-certs'); + + // Validate test results + await validateRunnerResults(page, { + totalRequests: 1, + passed: 1, + failed: 0, + skipped: 0 + }); }); }); \ No newline at end of file diff --git a/tests/utils/page/index.ts b/tests/utils/page/index.ts index 485f1b10a..69b3d32f1 100644 --- a/tests/utils/page/index.ts +++ b/tests/utils/page/index.ts @@ -1 +1,2 @@ export * from './actions'; +export * from './runner'; diff --git a/tests/utils/page/runner.ts b/tests/utils/page/runner.ts new file mode 100644 index 000000000..d6454b4ed --- /dev/null +++ b/tests/utils/page/runner.ts @@ -0,0 +1,191 @@ +import { Page, expect } from '../../../playwright'; + +/** + * 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 allButton = page.locator('button').filter({ hasText: /^All/ }); + const passedButton = page.locator('button').filter({ hasText: /^Passed/ }); + const failedButton = page.locator('button').filter({ hasText: /^Failed/ }); + const skippedButton = page.locator('button').filter({ hasText: /^Skipped/ }); + + const totalRequests = parseInt(await allButton.locator('span').innerText()); + const passed = parseInt(await passedButton.locator('span').innerText()); + const failed = parseInt(await failedButton.locator('span').innerText()); + const skipped = parseInt(await 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) => { + // Ensure collection is visible and loaded + const collectionContainer = page.locator('.collection-name').filter({ hasText: collectionName }); + await collectionContainer.waitFor({ state: 'visible' }); + // Wait a bit for the UI to stabilize + await page.waitForTimeout(300); + + // Open collection actions menu + await collectionContainer.locator('.collection-actions').hover(); + const icon = collectionContainer.locator('.collection-actions .icon'); + await icon.waitFor({ state: 'visible', timeout: 5000 }); + await page.waitForTimeout(200); // Small delay to ensure hover state is stable + await icon.click(); + + // Click Run menu item + await page.getByText('Run', { exact: true }).click(); + + // Handle runner tab - reset if needed, then run + const resetButton = page.getByRole('button', { name: 'Reset' }); + const runCollectionButton = page.getByRole('button', { name: 'Run Collection' }); + + // Check if Reset button is visible (means there are existing results) + const resetVisible = await resetButton.isVisible().catch(() => false); + if (resetVisible) { + await resetButton.click(); + // Wait a bit for the reset to complete + await page.waitForTimeout(500); + } + + // Now wait for and click Run Collection button + await runCollectionButton.waitFor({ state: 'visible', timeout: 10000 }); + await runCollectionButton.click(); + + // Wait for the run to complete + await page.getByRole('button', { name: 'Run Again' }).waitFor({ timeout: 2 * 60 * 1000 }); +}; + +/** + * 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') => { + // Click on the collection name - try sidebar first, then fall back to collection tab/name + // First try sidebar collection name (more reliable) + const sidebarCollection = page.locator('#sidebar-collection-name').filter({ hasText: collectionName }); + const sidebarExists = await sidebarCollection.count().then((count) => count > 0).catch(() => false); + + if (sidebarExists) { + await sidebarCollection.click(); + } else { + // Fall back to collection by title or text + const collectionByTitle = page.getByTitle(collectionName); + const collectionByText = page.getByText(collectionName); + const titleExists = await collectionByTitle.count().then((count) => count > 0).catch(() => false); + if (titleExists) { + await collectionByTitle.click(); + } else { + await collectionByText.click(); + } + } + + // Wait a moment for the UI to load + await page.waitForTimeout(300); + + // Check if there's already a mode selected - if so, we need to click the badge to open settings tab + // Look for the Developer Mode or Safe Mode badge/button + const developerModeBadge = page.locator('.developer-mode').filter({ hasText: 'Developer Mode' }); + const safeModeBadge = page.locator('.safe-mode').filter({ hasText: 'Safe Mode' }); + + const developerBadgeExists = await developerModeBadge.count().then((count) => count > 0).catch(() => false); + const safeBadgeExists = await safeModeBadge.count().then((count) => count > 0).catch(() => false); + + // If a badge exists, click it to open the security settings tab + if (developerBadgeExists || safeBadgeExists) { + // Click the appropriate badge to open the security settings tab + if (developerBadgeExists) { + await developerModeBadge.click(); + } else { + await safeModeBadge.click(); + } + + // Wait for the security settings tab to be active and form to be visible + // Look for the security settings content - it should have "JavaScript Sandbox" heading + await page.getByText('JavaScript Sandbox').waitFor({ state: 'visible', timeout: 10000 }); + await page.waitForTimeout(300); + } + // 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 + // These should be in the active tab (either modal or tab) + const safeModeRadio = page.getByLabel('Safe Mode'); + const developerRadio = page.getByLabel('Developer Mode(use only if'); + + // Wait for at least one of them to be visible + await Promise.race([ + safeModeRadio.waitFor({ state: 'visible', timeout: 10000 }).catch(() => {}), + developerRadio.waitFor({ state: 'visible', timeout: 10000 }).catch(() => {}) + ]); + + // Additional wait to ensure UI is stable + await page.waitForTimeout(300); + + if (mode === 'developer') { + await developerRadio.waitFor({ state: 'visible', timeout: 5000 }); + await developerRadio.check(); + } else { + // For safe mode, check if developer mode is currently selected + const developerModeChecked = await developerRadio.isChecked().catch(() => false); + + if (developerModeChecked) { + // Click the Developer Mode label text inside the security settings form + // Scope to the form container to avoid clicking the badge + // The form should have the "JavaScript Sandbox" heading, so scope to that container + 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(); + // Wait for UI to update + await page.waitForTimeout(300); + } + + // Ensure Safe Mode radio is visible and check it + await safeModeRadio.waitFor({ state: 'visible', timeout: 5000 }); + await safeModeRadio.check(); + } + + await page.getByRole('button', { name: 'Save' }).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); +}; From 3d8d93f20dfdf12fcfe07d79956305de77712c81 Mon Sep 17 00:00:00 2001 From: Sid Date: Fri, 14 Nov 2025 13:19:39 +0530 Subject: [PATCH 5/5] fix: add missing newline at end of file in RunnerResults component --- packages/bruno-app/src/components/RunnerResults/index.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/bruno-app/src/components/RunnerResults/index.jsx b/packages/bruno-app/src/components/RunnerResults/index.jsx index 8ce7b945f..ba6521be5 100644 --- a/packages/bruno-app/src/components/RunnerResults/index.jsx +++ b/packages/bruno-app/src/components/RunnerResults/index.jsx @@ -597,4 +597,4 @@ export default function RunnerResults({ collection }) {
); -} \ No newline at end of file +}