From 1d126dcb656e1e051f62cb5b6f0bab805511a833 Mon Sep 17 00:00:00 2001 From: Bijin A B Date: Sat, 14 Feb 2026 03:58:02 +0530 Subject: [PATCH] fix: flaky tests - standardize save keyboard shortcut across tests (#7141) --- .../moving-requests/tag-persistence.spec.ts | 3 +- tests/editable-table/editable-table.spec.ts | 3 +- .../collection-env-import.spec.ts | 1 + tests/grpc/make-request/make-request.spec.ts | 10 +++-- tests/grpc/metadata/with-bin-metadata.spec.ts | 3 +- .../file-types/invalid-file-handling.spec.ts | 4 +- .../import-insomnia-v4-environments.spec.ts | 1 + .../import-insomnia-v5-environments.spec.ts | 1 + .../insomnia/malformed-structure.spec.ts | 4 +- .../duplicate-operation-names-fix.spec.ts | 1 + .../import-openapi-with-examples.spec.ts | 2 + .../operation-name-with-newlines-fix.spec.ts | 1 + .../openapi/path-based-grouping.spec.ts | 1 + .../import-postman-with-examples.spec.ts | 1 + tests/import/postman/invalid-json.spec.ts | 4 +- .../postman/invalid-missing-info.spec.ts | 3 +- tests/import/postman/invalid-schema.spec.ts | 3 +- .../url-import/insomnia-url-import.spec.ts | 1 + .../url-import/openapi-url-import.spec.ts | 2 + .../url-import/postman-url-import.spec.ts | 1 + tests/import/wsdl/import-wsdl.spec.ts | 2 + tests/protobuf/manage-protofile.spec.ts | 4 +- .../newlines/newlines-persistence.spec.ts | 3 +- .../tests/custom-search/custom-search.spec.ts | 12 +++--- tests/response-examples/edit-example.spec.ts | 3 +- .../transient-requests.spec.ts | 6 ++- tests/websockets/persistence.spec.ts | 40 +++++++------------ 27 files changed, 66 insertions(+), 54 deletions(-) diff --git a/tests/collection/moving-requests/tag-persistence.spec.ts b/tests/collection/moving-requests/tag-persistence.spec.ts index 56a69ddb3..70f9652a1 100644 --- a/tests/collection/moving-requests/tag-persistence.spec.ts +++ b/tests/collection/moving-requests/tag-persistence.spec.ts @@ -99,7 +99,8 @@ test.describe('Tag persistence', () => { await locators.tags.input().fill('smoke'); await locators.tags.input().press('Enter'); await expect(locators.tags.item('smoke')).toBeVisible(); - await page.keyboard.press('Meta+s'); + const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + await page.keyboard.press(saveShortcut); // Create another folder await locators.sidebar.collectionRow('test-collection').hover(); diff --git a/tests/editable-table/editable-table.spec.ts b/tests/editable-table/editable-table.spec.ts index 27dd0204e..54f9aa9c7 100644 --- a/tests/editable-table/editable-table.spec.ts +++ b/tests/editable-table/editable-table.spec.ts @@ -33,7 +33,8 @@ test.describe('EditableTable - Focus and Placeholder', () => { await expect(nameInput).toBeFocused(); // Save the request - await page.keyboard.press('Meta+s'); + const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + await page.keyboard.press(saveShortcut); // Wait for save toast await expect(page.getByText('Request saved successfully').last()).toBeVisible(); diff --git a/tests/environments/import-environment/collection-env-import.spec.ts b/tests/environments/import-environment/collection-env-import.spec.ts index 559c210d8..eecdd7104 100644 --- a/tests/environments/import-environment/collection-env-import.spec.ts +++ b/tests/environments/import-environment/collection-env-import.spec.ts @@ -27,6 +27,7 @@ test.describe('Collection Environment Import Tests', () => { // Select a location and import await page.locator('#collection-location').fill(await createTmpDir('collection-env-import-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); await expect( page.locator('#sidebar-collection-name').filter({ hasText: 'Environment Test Collection' })).toBeVisible({ timeout: 10000 }); diff --git a/tests/grpc/make-request/make-request.spec.ts b/tests/grpc/make-request/make-request.spec.ts index 23cf45d9d..040c5d1e2 100644 --- a/tests/grpc/make-request/make-request.spec.ts +++ b/tests/grpc/make-request/make-request.spec.ts @@ -1,6 +1,8 @@ import { test, expect } from '../../../playwright'; import { buildGrpcCommonLocators } from '../../utils/page/locators'; +const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + test.describe('make grpc requests', () => { const setupGrpcTest = async (page) => { const locators = buildGrpcCommonLocators(page); @@ -53,7 +55,7 @@ test.describe('make grpc requests', () => { /* TODO: Reflection fetching incorrectly marks requests as modified, causing save indicators to appear. This save step prevents test timeouts by clearing the modified state. This is a temporary workaround until the reflection fetching issue is resolved. */ await test.step('save request via shortcut', async () => { - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); }); }); @@ -94,7 +96,7 @@ test.describe('make grpc requests', () => { /* TODO: Reflection fetching incorrectly marks requests as modified, causing save indicators to appear. This save step prevents test timeouts by clearing the modified state. This is a temporary workaround until the reflection fetching issue is resolved. */ await test.step('save request via shortcut', async () => { - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); }); }); @@ -144,7 +146,7 @@ test.describe('make grpc requests', () => { /* TODO: Reflection fetching incorrectly marks requests as modified, causing save indicators to appear. This save step prevents test timeouts by clearing the modified state. This is a temporary workaround until the reflection fetching issue is resolved. */ await test.step('save request via shortcut', async () => { - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); }); }); @@ -196,7 +198,7 @@ test.describe('make grpc requests', () => { /* TODO: Reflection fetching incorrectly marks requests as modified, causing save indicators to appear. This save step prevents test timeouts by clearing the modified state. This is a temporary workaround until the reflection fetching issue is resolved. */ await test.step('save request via shortcut', async () => { - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); }); }); }); diff --git a/tests/grpc/metadata/with-bin-metadata.spec.ts b/tests/grpc/metadata/with-bin-metadata.spec.ts index 6f01aa7ea..efaa9bf8f 100644 --- a/tests/grpc/metadata/with-bin-metadata.spec.ts +++ b/tests/grpc/metadata/with-bin-metadata.spec.ts @@ -26,7 +26,8 @@ test.describe('grpc metadata', () => { /* TODO: Reflection fetching incorrectly marks requests as modified, causing save indicators to appear. This save step prevents test timeouts by clearing the modified state. This is a temporary workaround until the reflection fetching issue is resolved. */ await test.step('save request via shortcut', async () => { - await page.keyboard.press('Meta+s'); + const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + await page.keyboard.press(saveShortcut); }); }); }); diff --git a/tests/import/file-types/invalid-file-handling.spec.ts b/tests/import/file-types/invalid-file-handling.spec.ts index f8346f6f3..936aff0c6 100644 --- a/tests/import/file-types/invalid-file-handling.spec.ts +++ b/tests/import/file-types/invalid-file-handling.spec.ts @@ -18,8 +18,8 @@ test.describe('Invalid File Handling', () => { // Wait for the loader to disappear await page.locator('#import-collection-loader').waitFor({ state: 'hidden' }); - const hasError = await page.getByText('Failed to parse the file – ensure it is valid JSON or YAML').first().isVisible(); - expect(hasError).toBe(true); + // Use auto-retrying assertion instead of snapshot isVisible() check + await expect(page.getByText('Failed to parse the file – ensure it is valid JSON or YAML').first()).toBeVisible(); // Cleanup: close any open modals await page.getByTestId('modal-close-button').click(); diff --git a/tests/import/insomnia/import-insomnia-v4-environments.spec.ts b/tests/import/insomnia/import-insomnia-v4-environments.spec.ts index 3f8882ee6..fe564c5da 100644 --- a/tests/import/insomnia/import-insomnia-v4-environments.spec.ts +++ b/tests/import/insomnia/import-insomnia-v4-environments.spec.ts @@ -39,6 +39,7 @@ test.describe('Import Insomnia v4 Collection - Environment Import', () => { await page.locator('#collection-location').fill(await createTmpDir('insomnia-v4-env-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); await expect(page.locator('#sidebar-collection-name').getByText('Test API Collection v4 with Environments')).toBeVisible(); diff --git a/tests/import/insomnia/import-insomnia-v5-environments.spec.ts b/tests/import/insomnia/import-insomnia-v5-environments.spec.ts index dda31a960..8a3f1e1e9 100644 --- a/tests/import/insomnia/import-insomnia-v5-environments.spec.ts +++ b/tests/import/insomnia/import-insomnia-v5-environments.spec.ts @@ -38,6 +38,7 @@ test.describe('Import Insomnia v5 Collection - Environment Import', () => { await page.locator('#collection-location').fill(await createTmpDir('insomnia-v5-env-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); await openCollection(page, 'Test API Collection v5 with Environments'); }); diff --git a/tests/import/insomnia/malformed-structure.spec.ts b/tests/import/insomnia/malformed-structure.spec.ts index 03156cd61..cb4334e67 100644 --- a/tests/import/insomnia/malformed-structure.spec.ts +++ b/tests/import/insomnia/malformed-structure.spec.ts @@ -16,8 +16,8 @@ test.describe('Invalid Insomnia Collection - Malformed Structure', () => { await page.setInputFiles('input[type="file"]', insomniaFile); // Check for error message - this should fail during JSON parsing - const hasError = await page.getByText('Failed to parse the file').first().isVisible(); - expect(hasError).toBe(true); + // Use auto-retrying assertion instead of snapshot isVisible() check + await expect(page.getByText('Failed to parse the file').first()).toBeVisible(); // Cleanup: close any open modals await page.getByTestId('modal-close-button').click(); diff --git a/tests/import/openapi/duplicate-operation-names-fix.spec.ts b/tests/import/openapi/duplicate-operation-names-fix.spec.ts index 4c545afd8..655e170d3 100644 --- a/tests/import/openapi/duplicate-operation-names-fix.spec.ts +++ b/tests/import/openapi/duplicate-operation-names-fix.spec.ts @@ -31,6 +31,7 @@ test.describe('OpenAPI Duplicate Names Handling', () => { // select a location await page.locator('#collection-location').fill(await createTmpDir('duplicate-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // verify the collection was imported successfully await expect(page.locator('#sidebar-collection-name').getByText('Duplicate Test Collection')).toBeVisible(); diff --git a/tests/import/openapi/import-openapi-with-examples.spec.ts b/tests/import/openapi/import-openapi-with-examples.spec.ts index 7fa6193b7..121f22330 100644 --- a/tests/import/openapi/import-openapi-with-examples.spec.ts +++ b/tests/import/openapi/import-openapi-with-examples.spec.ts @@ -75,6 +75,7 @@ test.describe('Import OpenAPI Collection with Examples', () => { await test.step('Complete import by clicking import button', async () => { const locationModal = page.locator('[data-testid="import-collection-location-modal"]'); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); }); await test.step('Handle sandbox modal', async () => { @@ -203,6 +204,7 @@ test.describe('Import OpenAPI Collection with Examples', () => { await test.step('Complete import by clicking import button', async () => { const locationModal = page.locator('[data-testid="import-collection-location-modal"]'); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); }); await test.step('Handle sandbox modal', async () => { diff --git a/tests/import/openapi/operation-name-with-newlines-fix.spec.ts b/tests/import/openapi/operation-name-with-newlines-fix.spec.ts index 3ffd73934..c086ebecd 100644 --- a/tests/import/openapi/operation-name-with-newlines-fix.spec.ts +++ b/tests/import/openapi/operation-name-with-newlines-fix.spec.ts @@ -30,6 +30,7 @@ test.describe('OpenAPI Newline Handling', () => { // select a location await page.locator('#collection-location').fill(await createTmpDir('newline-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // verify the collection was imported successfully await expect(page.locator('#sidebar-collection-name').getByText('Newline Test Collection')).toBeVisible(); diff --git a/tests/import/openapi/path-based-grouping.spec.ts b/tests/import/openapi/path-based-grouping.spec.ts index e6fbe2cbb..3aba4d73a 100644 --- a/tests/import/openapi/path-based-grouping.spec.ts +++ b/tests/import/openapi/path-based-grouping.spec.ts @@ -34,6 +34,7 @@ test.describe('OpenAPI Path-Based Grouping', () => { // Select a location and import await page.locator('#collection-location').fill(await createTmpDir('path-grouping-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // Verify the collection was imported successfully await expect(page.locator('#sidebar-collection-name').getByText('Path Grouping Test API')).toBeVisible(); diff --git a/tests/import/postman/import-postman-with-examples.spec.ts b/tests/import/postman/import-postman-with-examples.spec.ts index 8f2617ad6..87c6b7bc6 100644 --- a/tests/import/postman/import-postman-with-examples.spec.ts +++ b/tests/import/postman/import-postman-with-examples.spec.ts @@ -79,6 +79,7 @@ test.describe('Import Postman Collection with Examples', () => { await test.step('Complete import by clicking import button', async () => { const locationModal = page.locator('[data-testid="import-collection-location-modal"]'); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); }); await test.step('Open collection', async () => { diff --git a/tests/import/postman/invalid-json.spec.ts b/tests/import/postman/invalid-json.spec.ts index 6183ca03f..3d2727f39 100644 --- a/tests/import/postman/invalid-json.spec.ts +++ b/tests/import/postman/invalid-json.spec.ts @@ -16,9 +16,7 @@ test.describe('Invalid Postman Collection - Invalid JSON', () => { await page.setInputFiles('input[type="file"]', postmanFile); // Check for error message - const hasError = await page.getByText('Unsupported collection format').first().isVisible(); - - expect(hasError).toBe(true); + await expect(page.getByText('Unsupported collection format').first()).toBeVisible(); // Cleanup: close any open modals await page.getByTestId('modal-close-button').click(); diff --git a/tests/import/postman/invalid-missing-info.spec.ts b/tests/import/postman/invalid-missing-info.spec.ts index 95141631d..c95acebc5 100644 --- a/tests/import/postman/invalid-missing-info.spec.ts +++ b/tests/import/postman/invalid-missing-info.spec.ts @@ -16,8 +16,7 @@ test.describe('Invalid Postman Collection - Missing Info', () => { await page.setInputFiles('input[type="file"]', postmanFile); // Check for error message - const hasError = await page.getByText('Unsupported collection format').first().isVisible(); - expect(hasError).toBe(true); + await expect(page.getByText('Unsupported collection format').first()).toBeVisible(); // Cleanup: close any open modals await page.getByTestId('modal-close-button').click(); diff --git a/tests/import/postman/invalid-schema.spec.ts b/tests/import/postman/invalid-schema.spec.ts index f1dbee6fd..8e126ff4c 100644 --- a/tests/import/postman/invalid-schema.spec.ts +++ b/tests/import/postman/invalid-schema.spec.ts @@ -16,8 +16,7 @@ test.describe('Invalid Postman Collection - Invalid Schema', () => { await page.setInputFiles('input[type="file"]', postmanFile); // Check for error message - const hasError = await page.getByText('Unsupported collection format').first().isVisible(); - expect(hasError).toBe(true); + await expect(page.getByText('Unsupported collection format').first()).toBeVisible(); // Cleanup: close any open modals await page.getByTestId('modal-close-button').click(); diff --git a/tests/import/url-import/insomnia-url-import.spec.ts b/tests/import/url-import/insomnia-url-import.spec.ts index 3a3d51643..e2123b2b1 100644 --- a/tests/import/url-import/insomnia-url-import.spec.ts +++ b/tests/import/url-import/insomnia-url-import.spec.ts @@ -32,6 +32,7 @@ test.describe('Insomnia URL Import', () => { // Select a location and import await page.locator('#collection-location').fill(await createTmpDir('test-api-collection-v5')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // Verify the collection was imported successfully and configure it await expect(page.locator('#sidebar-collection-name').getByText('Test API Collection v5')).toBeVisible(); diff --git a/tests/import/url-import/openapi-url-import.spec.ts b/tests/import/url-import/openapi-url-import.spec.ts index 3e19e4110..967ec6d67 100644 --- a/tests/import/url-import/openapi-url-import.spec.ts +++ b/tests/import/url-import/openapi-url-import.spec.ts @@ -36,6 +36,7 @@ test.describe('OpenAPI URL Import', () => { // Select a location and import with default grouping (tags) await page.locator('#collection-location').fill(await createTmpDir('swagger-petstore')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // Verify the collection was imported successfully and configure it await expect(page.locator('#sidebar-collection-name').getByText('Swagger Petstore')).toBeVisible(); @@ -82,6 +83,7 @@ test.describe('OpenAPI URL Import', () => { // Select a location and import with path-based grouping await page.locator('#collection-location').fill(await createTmpDir('swagger-petstore-path')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // Verify the collection was imported successfully and configure it await expect(page.locator('#sidebar-collection-name').getByText('Swagger Petstore')).toBeVisible(); diff --git a/tests/import/url-import/postman-url-import.spec.ts b/tests/import/url-import/postman-url-import.spec.ts index 35d8566f0..1c7a38813 100644 --- a/tests/import/url-import/postman-url-import.spec.ts +++ b/tests/import/url-import/postman-url-import.spec.ts @@ -32,6 +32,7 @@ test.describe('Postman URL Import', () => { // Select a location and import await page.locator('#collection-location').fill(await createTmpDir('postman-v21-collection')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); // Verify the collection was imported successfully and configure it await expect(page.locator('#sidebar-collection-name').getByText('Postman v2.1 Collection')).toBeVisible(); diff --git a/tests/import/wsdl/import-wsdl.spec.ts b/tests/import/wsdl/import-wsdl.spec.ts index f64c6efb3..a13900429 100644 --- a/tests/import/wsdl/import-wsdl.spec.ts +++ b/tests/import/wsdl/import-wsdl.spec.ts @@ -37,6 +37,7 @@ test.describe('Import WSDL Collection', () => { // select a location await page.locator('#collection-location').fill(await createTmpDir('wsdl-xml-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); await expect(page.locator('#sidebar-collection-name').getByText('TestWSDLServiceXML')).toBeVisible(); }); @@ -98,6 +99,7 @@ test.describe('Import WSDL Collection', () => { // select a location await page.locator('#collection-location').fill(await createTmpDir('wsdl-json-test')); await locationModal.getByRole('button', { name: 'Import' }).click(); + await locationModal.waitFor({ state: 'hidden' }); }); await test.step('Verify that the collection was imported successfully', async () => { diff --git a/tests/protobuf/manage-protofile.spec.ts b/tests/protobuf/manage-protofile.spec.ts index e96d17019..a1281b574 100644 --- a/tests/protobuf/manage-protofile.spec.ts +++ b/tests/protobuf/manage-protofile.spec.ts @@ -127,8 +127,8 @@ test.describe('manage protofile', () => { // Use more specific selector for proto file selection await page.locator('div').filter({ hasText: /^product\.proto\.\.\/protos\/services\/product\.proto$/ }).first().click(); - const loadedMethodsMessage = await page.getByText('Failed to load gRPC methods: Unknown error').first().isVisible(); - expect(loadedMethodsMessage).toBe(true); + // Verify the error message is visible (auto-retrying) + await expect(page.getByText('Failed to load gRPC methods: Unknown error').first()).toBeVisible(); // Check that methods dropdown is not visible when loading fails const methodsDropdown = page.getByTestId('grpc-methods-dropdown'); diff --git a/tests/request/newlines/newlines-persistence.spec.ts b/tests/request/newlines/newlines-persistence.spec.ts index d15ab0fc5..e8ec065aa 100644 --- a/tests/request/newlines/newlines-persistence.spec.ts +++ b/tests/request/newlines/newlines-persistence.spec.ts @@ -47,7 +47,8 @@ test('should persist request with newlines across app restarts', async ({ create await getTableCell(postResRow, 1).locator('.CodeMirror').click(); await getTableCell(postResRow, 1).locator('textarea').fill('post\nResponse\nValue'); - await page.keyboard.press('Meta+s'); + const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + await page.keyboard.press(saveShortcut); await app1.close(); // Verify persistence after restart diff --git a/tests/request/tests/custom-search/custom-search.spec.ts b/tests/request/tests/custom-search/custom-search.spec.ts index 9806782b4..624aeefe8 100644 --- a/tests/request/tests/custom-search/custom-search.spec.ts +++ b/tests/request/tests/custom-search/custom-search.spec.ts @@ -1,5 +1,7 @@ import { test, expect } from '../../../../playwright'; +const findShortcut = process.platform === 'darwin' ? 'Meta+f' : 'Control+f'; + test.describe('Custom Search Functionality in Scripts Tab', () => { test('should open search box when Cmd+F or Ctrl+F is pressed in scripts tab', async ({ pageWithUserData: page }) => { await page.getByTestId('collections').locator('#sidebar-collection-name').filter({ hasText: 'custom-search' }).click(); @@ -22,7 +24,7 @@ test.describe('Custom Search Functionality in Scripts Tab', () => { const preContent = await preRequestEditor.textContent(); console.log('Pre Request content loaded:', preContent?.substring(0, 100)); - await page.keyboard.press('Meta+f'); + await page.keyboard.press(findShortcut); // Verify search box appears const preEditorSearchBar = page.getByTestId('pre-request-script-editor'); @@ -74,7 +76,7 @@ test.describe('Custom Search Functionality in Scripts Tab', () => { const preRequestEditor = page.getByTestId('pre-request-script-editor').locator('.CodeMirror').first(); const preTextarea = preRequestEditor.locator('textarea[tabindex="0"]'); await preTextarea.focus(); - await page.keyboard.press('Meta+f'); + await page.keyboard.press(findShortcut); const preSearchInput = page.getByTestId('pre-request-script-editor').locator('.bruno-search-bar input[placeholder="Search..."]'); await preSearchInput.fill('uniquePreVar'); @@ -87,7 +89,7 @@ test.describe('Custom Search Functionality in Scripts Tab', () => { const postResponseEditor = page.getByTestId('post-response-script-editor').locator('.CodeMirror').first(); const postTextarea = postResponseEditor.locator('textarea[tabindex="0"]'); await postTextarea.focus(); - await page.keyboard.press('Meta+f'); + await page.keyboard.press(findShortcut); const postSearchInput = page.getByTestId('post-response-script-editor').locator('.bruno-search-bar input[placeholder="Search..."]'); await postSearchInput.fill('uniquePostVar'); @@ -108,7 +110,7 @@ test.describe('Custom Search Functionality in Scripts Tab', () => { const preRequestEditor = page.getByTestId('pre-request-script-editor').locator('.CodeMirror').first(); const preTextarea = preRequestEditor.locator('textarea[tabindex="0"]'); await preTextarea.focus(); - await page.keyboard.press('Meta+f'); + await page.keyboard.press(findShortcut); const preSearchInput = page.getByTestId('pre-request-script-editor').locator('.bruno-search-bar input[placeholder="Search..."]'); await preSearchInput.fill('commonVar'); @@ -121,7 +123,7 @@ test.describe('Custom Search Functionality in Scripts Tab', () => { const postResponseEditor = page.getByTestId('post-response-script-editor').locator('.CodeMirror').first(); const postTextarea = postResponseEditor.locator('textarea[tabindex="0"]'); await postTextarea.focus(); - await page.keyboard.press('Meta+f'); + await page.keyboard.press(findShortcut); const postSearchInput = page.getByTestId('post-response-script-editor').locator('.bruno-search-bar input[placeholder="Search..."]'); await postSearchInput.fill('postVar'); diff --git a/tests/response-examples/edit-example.spec.ts b/tests/response-examples/edit-example.spec.ts index 41abc3b9d..f22117806 100644 --- a/tests/response-examples/edit-example.spec.ts +++ b/tests/response-examples/edit-example.spec.ts @@ -176,7 +176,8 @@ test.describe.serial('Edit Response Examples', () => { await page.getByTestId('response-example-edit-btn').click(); await page.getByTestId('response-example-name-input').clear(); await page.getByTestId('response-example-name-input').fill('Keyboard Shortcut Test'); - await page.keyboard.press('Meta+s'); + const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + await page.keyboard.press(saveShortcut); await expect(page.getByTestId('response-example-title')).toHaveText('edit-example / Keyboard Shortcut Test'); }); }); diff --git a/tests/transient-requests/transient-requests.spec.ts b/tests/transient-requests/transient-requests.spec.ts index cb18fd644..e47fb8873 100644 --- a/tests/transient-requests/transient-requests.spec.ts +++ b/tests/transient-requests/transient-requests.spec.ts @@ -2,6 +2,8 @@ import { test, expect } from '../../playwright'; import { createTransientRequest, fillRequestUrl, closeAllCollections, createCollection, sendRequest, clickResponseAction, selectRequestPaneTab } from '../utils/page'; import { buildCommonLocators, buildWebsocketCommonLocators } from '../utils/page/locators'; +const saveShortcut = process.platform === 'darwin' ? 'Meta+s' : 'Control+s'; + test.describe.serial('Transient Requests', () => { let locators: ReturnType; @@ -123,7 +125,7 @@ test.describe.serial('Transient Requests', () => { await test.step('Trigger save action using keyboard shortcut', async () => { // Try to save using Cmd+S (Mac) or Ctrl+S (other platforms) - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); await page.waitForTimeout(500); }); @@ -171,7 +173,7 @@ test.describe.serial('Transient Requests', () => { }); await test.step('Trigger save action using keyboard shortcut', async () => { - await page.keyboard.press('Meta+s'); + await page.keyboard.press(saveShortcut); await page.waitForTimeout(500); }); diff --git a/tests/websockets/persistence.spec.ts b/tests/websockets/persistence.spec.ts index e5f1c7d7c..7fbfc85e7 100644 --- a/tests/websockets/persistence.spec.ts +++ b/tests/websockets/persistence.spec.ts @@ -2,9 +2,9 @@ import { expect, Locator, test } from '../../playwright'; import { buildWebsocketCommonLocators } from '../utils/page/locators'; import { readFile, writeFile } from 'fs/promises'; import { join } from 'path'; -import { waitForPredicate } from '../utils/wait'; const BRU_REQ_NAME = /^base$/; +const BRU_PATH = join(__dirname, 'fixtures/collection/base.bru'); // TODO: reaper move to someplace common const isRequestSaved = async (saveButton: Locator) => { @@ -14,53 +14,43 @@ const isRequestSaved = async (saveButton: Locator) => { test.describe.serial('persistence', () => { let originalUrl = ''; - let originalContext = { - path: join(__dirname, 'fixtures/collection/base.bru'), - data: '' - }; + let originalData = ''; test.beforeAll(async () => { - // Store original request data to simplify test consistency - originalContext.data = await readFile(originalContext.path, 'utf8'); - const originalUrlMatch = originalContext.data.match(`(url)\s*\:\s*(.+)`); + originalData = await readFile(BRU_PATH, 'utf8'); + const originalUrlMatch = originalData.match(`(url)\s*\:\s*(.+)`); if (!originalUrlMatch) { throw new Error('url not found in bru file for websocket'); } - originalUrl = originalUrlMatch[0].replace(/url\:/, ''); + // Trim to remove leading/trailing whitespace from the regex capture + originalUrl = originalUrlMatch[0].replace(/url\:/, '').trim(); }); test.afterAll(async () => { - // Write back the original request information - await writeFile(originalContext.path, originalContext.data, 'utf8'); + // Restore original fixture since pageWithUserData does not isolate collection files + await writeFile(BRU_PATH, originalData, 'utf8'); }); test('save new websocket url', async ({ pageWithUserData: page }) => { const replacementUrl = 'ws://localhost:8083'; const locators = buildWebsocketCommonLocators(page); - - const clearText = async (text: string) => { - for (let i = text.length; i > 0; i--) { - await page.keyboard.press('Backspace'); - } - }; + const selectAllShortcut = process.platform === 'darwin' ? 'Meta+a' : 'Control+a'; await page.locator('#sidebar-collection-name').click(); await page.getByTitle(BRU_REQ_NAME).click(); - // remove the original url from the request + // Select all text in the URL input and replace with new URL await page.locator('.input-container').filter({ hasText: originalUrl }).first().click(); - await clearText(originalUrl); - - // replace it with an arbritrary url + await page.keyboard.press(selectAllShortcut); await page.keyboard.insertText(replacementUrl); - // check if the request is now unsaved - await expect(await isRequestSaved(locators.saveButton())).toBe(false); + // Use auto-retrying assertion to check if the request is now unsaved + await expect.poll(() => isRequestSaved(locators.saveButton())).toBe(false); await locators.saveButton().click(); - const result = await waitForPredicate(() => isRequestSaved(locators.saveButton())); - await expect(result).toBe(true); + // Use auto-retrying assertion to verify save completed + await expect.poll(() => isRequestSaved(locators.saveButton())).toBe(true); // check if the replacementUrl is now visually available await expect(page.locator('.input-container').filter({ hasText: replacementUrl }).first()).toBeAttached();