mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-25 13:45:52 +00:00
* feat: add functionality to retrieve collection path from transient file requests in IPC module * feat: implement transient directory handling in collection mounting process * add action to store transient directory paths in Redux state * update IPC handler to create and return a temporary directory for collections * modify collection mount action to dispatch transient directory addition * feat: add CreateTransientRequest component for managing transient requests * implement CreateTransientRequest component to facilitate the creation of HTTP, GraphQL, gRPC, and WebSocket transient requests * integrate the component into RequestTabs for user interaction * update collection and request handling to differentiate between transient and non-transient requests * enhance Redux actions to support transient request creation and management * feat: enhance transient request handling and add temp directory watcher * refactor Redux actions for HTTP, gRPC, and WebSocket requests to utilize a unified task queue for transient requests * implement a new helper function to retrieve collection paths from temporary directory metadata * add functionality to watch transient directories for file changes, excluding metadata.json * integrate transient directory watcher into the collection mounting process * feat: enhance transient request management with temp directory integration * update generateTransientRequestName function to accept tempDirectory parameter for improved request naming * modify CreateTransientRequest component to utilize tempDirectory for transient request creation * adjust middleware to check for transient status based on tempDirectory * implement transient file and directory identification in collections slice for better state management * feat: add SaveTransientRequest component for managing transient requests * implement SaveTransientRequest component to facilitate saving transient requests to selected folders * create StyledWrapper for component styling * introduce useCollectionFolderTree hook for managing folder navigation and state * update Redux actions to handle saving requests from transient state * feat: implement SaveTransientRequestContainer and enhance modal management * add SaveTransientRequestContainer to manage multiple transient request modals * refactor SaveTransientRequest component to utilize Redux for modal state management * implement open and close actions for transient request modals in Redux slice * update Bruno page to include SaveTransientRequestContainer for improved UI integration * feat: enhance SaveTransientRequest component with new folder creation functionality * add input for creating new folders within the SaveTransientRequest component * implement validation for new folder names and filesystem names * integrate folder creation logic with Redux actions for better state management * update styling for new folder input elements in StyledWrapper * improve modal behavior to reset state when opened * feat: update CreateTransientRequest to utilize collection presets for request URLs * Refactored CreateTransientRequest component to retrieve request URLs from collection presets. * Enhanced request handling by dynamically setting request URLs based on the selected collection's configuration. * refactor: clean up unused imports and adjust request handling in collections actions * Removed unused imports from actions.js to streamline the code. * Updated the saveRequest function to reject the modal instead of resolving it when handling transient requests. * Cleaned up comments in index.js for better clarity. * refactor: streamline transient request handling and improve save functionality * Removed success toast notifications from CreateTransientRequest component to simplify user feedback. * Enhanced SaveTransientRequest component to handle transient requests more effectively, including improved filename resolution and validation. * Added IPC handler for saving transient requests, ensuring proper file management and error handling. * Updated Redux actions to check for duplicate transient request names within the temporary directory. * feat: enhance request handling in ConfirmCollectionCloseDrafts component * Added logic to differentiate between transient and non-transient drafts, ensuring transient requests are saved individually before closing the collection. * Improved user feedback by displaying unsaved changes for both regular and transient requests. * Updated save and discard functionality to handle all drafts appropriately, enhancing overall user experience. * fix:fixed useCallback dependency array * fix:added request name checks before save * fix: added isTransient to files * fix: added watcher cleanup for temp directory * refactor: enhance transient request handling and optimize component logic * Updated CreateTransientRequest to utilize useMemo for improved performance and prevent unnecessary re-renders. * Refactored generateTransientRequestName to focus solely on transient requests, removing tempDirectory dependency. * Streamlined SaveTransientRequest by consolidating form reset logic and removing unused state variables. * Improved ConfirmCollectionCloseDrafts to differentiate between transient and non-transient drafts more effectively. * Cleaned up imports and optimized Redux actions for better maintainability. * feat: implement transient request file deletion on tab close * Added middleware to handle the deletion of transient request files when tabs are closed. * Enhanced collection-watcher to unlink temporary files, ensuring metadata.json is skipped and only request files are processed. * Improved error handling for file deletion operations. * feat: enhance autosave middleware to skip transient requests * Updated autosave middleware to check for transient requests and skip auto-save operations accordingly. * fix: update ConfirmCollectionCloseDrafts to display all transient drafts * Modified the ConfirmCollectionCloseDrafts component to show all transient drafts without limiting the display to a maximum number. * Removed the conditional message for additional drafts not shown, enhancing the user experience by providing complete visibility of transient requests. * feat: enhance SaveTransientRequest component for better modal management * Refactored SaveTransientRequest and its container to improve modal handling for unsaved transient requests. * Introduced state management for opening specific modals and added functionality to discard all unsaved requests. * Updated Redux actions to manage transient request modals more effectively, ensuring no duplicates are added. * Enhanced user interface to display a list of unsaved requests with options to save or discard them. * feat: improve modal management in SaveTransientRequestContainer * Added useEffect to reset openItemUid when the corresponding modal is no longer present. * Implemented functionality to close all tabs associated with transient requests and show a success message upon discarding them. * Removed unnecessary modal close handler and streamlined modal opening logic for better clarity and performance. * refactor: streamline code formatting and improve readability in collection actions * Consolidated multiple lines of code into single lines for better readability in ConfirmCollectionCloseDrafts and actions.js. * Enhanced consistency in the formatting of function parameters and return statements across the collections slice. * Removed unnecessary line breaks and improved the structure of the code for easier maintenance. * refactor: improve code readability and structure in middleware and actions * Consolidated multiple lines of code into single lines for better readability in middleware.js and actions.js. * Enhanced consistency in formatting function parameters and return statements across the collections slice. * Removed unnecessary line breaks and improved the structure of the code for easier maintenance. * Streamlined dispatch calls for better clarity and performance. * refactor: enhance code readability and consistency in middleware and actions * Improved formatting and structure in middleware.js for dispatch calls. * Streamlined comments and indentation in actions.js for better clarity. * Consolidated multiple lines into single lines where appropriate to enhance readability. * refactor: enhance transient request handling and modal interactions * Improved the modal handling logic for removing collections to differentiate between regular and drafts confirmation modals. * Added new tests for creating and saving transient requests (HTTP, GraphQL, gRPC, WebSocket) ensuring they do not appear in the sidebar until saved. * Introduced utility functions for creating transient requests and filling request URLs, improving code reusability and clarity. * refactor: simplify transient request modal rendering and improve collection watcher logic * Introduced a new TransientRequestModalsRenderer component to streamline modal rendering based on the number of transient requests. * Refactored the collection watcher logic to enhance readability by removing unnecessary setTimeout and consolidating file handling functions. * Improved error handling and logging for the temp directory watcher. * fix: correct spelling of 'WebSocket' in transient request components and tests * Updated the spelling of 'Websocket' to 'WebSocket' in CreateTransientRequest component, transient requests test, and action type definitions for consistency and accuracy.
138 lines
6.1 KiB
TypeScript
138 lines
6.1 KiB
TypeScript
import path from 'path';
|
|
import { test, expect, errors } from '../../playwright';
|
|
|
|
const env = {
|
|
DISABLE_SAMPLE_COLLECTION_IMPORT: 'false'
|
|
};
|
|
|
|
test.describe('Onboarding', () => {
|
|
test('should create sample collection on first launch', async ({ launchElectronApp, createTmpDir }) => {
|
|
// Use a fresh app instance to avoid contamination from previous tests
|
|
const userDataPath = await createTmpDir('onboarding-fresh');
|
|
const app = await launchElectronApp({ userDataPath, dotEnv: env });
|
|
const page = await app.firstWindow();
|
|
|
|
// Verify sample collection appears in sidebar
|
|
const sampleCollection = page.locator('#sidebar-collection-name').getByText('Sample API Collection');
|
|
await expect(sampleCollection).toBeVisible();
|
|
|
|
// Click on the sample collection to open it
|
|
await sampleCollection.click();
|
|
|
|
// Verify the sample request is visible and clickable
|
|
const request = page.locator('.collection-item-name').getByText('Get Users');
|
|
await expect(request).toBeVisible();
|
|
await request.click();
|
|
|
|
// Verify the URL is set correctly
|
|
await expect(page.locator('#request-url')).toContainText('https://jsonplaceholder.typicode.com/users');
|
|
|
|
// Clean up
|
|
await app.close();
|
|
});
|
|
|
|
test('should not create duplicate collections on subsequent launches', async ({ launchElectronApp, createTmpDir }) => {
|
|
// Use a fresh app instance to avoid contamination from previous tests
|
|
const userDataPath = await createTmpDir('duplicate-collections');
|
|
const app = await launchElectronApp({ userDataPath, dotEnv: env });
|
|
const page = await app.firstWindow();
|
|
|
|
// First launch - verify sample collection is created
|
|
const sampleCollection = page.locator('#sidebar-collection-name').getByText('Sample API Collection');
|
|
await expect(sampleCollection).toBeVisible();
|
|
await sampleCollection.click();
|
|
|
|
// Verify the sample request
|
|
const request = page.locator('.collection-item-name').getByText('Get Users');
|
|
await expect(request).toBeVisible();
|
|
await request.click();
|
|
|
|
// Verify the URL is set correctly
|
|
await expect(page.locator('#request-url')).toContainText('https://jsonplaceholder.typicode.com/users');
|
|
|
|
// Close the first app instance
|
|
await app.close();
|
|
|
|
// Restart app - should not create sample collection again
|
|
const newApp = await launchElectronApp({ userDataPath, dotEnv: env });
|
|
const newPage = await newApp.firstWindow();
|
|
|
|
// Verify only one sample collection exists
|
|
const sampleCollections = newPage.locator('#sidebar-collection-name').getByText('Sample API Collection');
|
|
await expect(sampleCollections).toHaveCount(1);
|
|
|
|
// Verify the collection still works after restart
|
|
await sampleCollections.click();
|
|
const request2 = newPage.locator('.collection-item-name').getByText('Get Users');
|
|
await expect(request2).toBeVisible();
|
|
await request2.click();
|
|
|
|
// Verify the URL is still correct after restart
|
|
await expect(newPage.locator('#request-url')).toContainText('https://jsonplaceholder.typicode.com/users');
|
|
|
|
// Clean up
|
|
await newApp.close();
|
|
});
|
|
|
|
test('should not recreate sample collection after user deletes it', async ({ launchElectronApp, reuseOrLaunchElectronApp, createTmpDir }) => {
|
|
const userDataPath = await createTmpDir('first-launch');
|
|
const app = await launchElectronApp({ userDataPath, dotEnv: env });
|
|
const page = await app.firstWindow();
|
|
|
|
// First launch - sample collection should be created
|
|
const sampleCollection = page.getByTestId('collections').locator('.collection-name').filter({ hasText: 'Sample API Collection' });
|
|
await expect(sampleCollection).toBeVisible();
|
|
|
|
// User removes the sample collection from workspace (hover on the collection and open context menu)
|
|
await sampleCollection.hover();
|
|
await sampleCollection.locator('.collection-actions .icon').click();
|
|
|
|
// Remove the sample collection
|
|
const removeOption = page.locator('.dropdown-item').getByText('Remove');
|
|
await expect(removeOption).toBeVisible();
|
|
await removeOption.click();
|
|
|
|
// Wait for modal to appear - could be either regular remove or drafts confirmation
|
|
const removeModal = page.locator('.bruno-modal').filter({ hasText: 'Remove Collection' });
|
|
await removeModal.waitFor({ state: 'visible', timeout: 5000 });
|
|
|
|
// Check if it's the drafts confirmation modal (has "Discard All and Remove" button)
|
|
const hasDiscardButton = await page.getByRole('button', { name: 'Discard All and Remove' }).isVisible().catch(() => false);
|
|
|
|
if (hasDiscardButton) {
|
|
// Drafts modal - click "Discard All and Remove"
|
|
await page.getByRole('button', { name: 'Discard All and Remove' }).click();
|
|
} else {
|
|
// Regular modal - click the submit button
|
|
await page.locator('.bruno-modal-footer .submit').click();
|
|
}
|
|
|
|
// Verify collection is closed (no longer visible in sidebar)
|
|
await expect(sampleCollection).not.toBeVisible();
|
|
|
|
// Restart app - sample collection should NOT be recreated
|
|
const newApp = await reuseOrLaunchElectronApp({ userDataPath, dotEnv: env });
|
|
const newPage = await newApp.firstWindow();
|
|
|
|
// Wait for the app to be loaded / onboarding to be completed
|
|
await newPage.locator('[data-app-state="loaded"]').waitFor();
|
|
|
|
// Sample collection should not appear since it's no longer first launch
|
|
const sampleCollections = newPage.locator('#sidebar-collection-name').getByText('Sample API Collection');
|
|
await expect(sampleCollections).not.toBeVisible();
|
|
});
|
|
|
|
test('should not create sample collection if user has already opened a collection', async ({ pageWithUserData: page }) => {
|
|
// Wait for the app to be loaded / onboarding to be completed
|
|
await page.locator('[data-app-state="loaded"]').waitFor();
|
|
|
|
// This test simulates old users who already have a collection opened
|
|
const brunoTestbench = page.locator('#sidebar-collection-name').getByText('bruno-testbench');
|
|
await expect(brunoTestbench).toBeVisible();
|
|
|
|
// Verify no sample collection was created since user already has collections
|
|
const sampleCollection = page.locator('#sidebar-collection-name').getByText('Sample API Collection');
|
|
await expect(sampleCollection).not.toBeVisible();
|
|
});
|
|
});
|