mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-26 14:15:52 +00:00
feat: request restore (#7948)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { useCallback, useState, useRef, Fragment, useMemo, useEffect } from 'react';
|
||||
import get from 'lodash/get';
|
||||
import { makeTabPermanent } from 'providers/ReduxStore/slices/tabs';
|
||||
import { makeTabPermanent, syncTabUid } from 'providers/ReduxStore/slices/tabs';
|
||||
import { saveRequest, saveCollectionRoot, saveFolderRoot, saveEnvironment, saveCollectionSettings, closeTabs } from 'providers/ReduxStore/slices/collections/actions';
|
||||
import useKeybinding from 'hooks/useKeybinding';
|
||||
import { deleteRequestDraft, deleteCollectionDraft, deleteFolderDraft, clearEnvironmentsDraft } from 'providers/ReduxStore/slices/collections';
|
||||
@@ -46,6 +46,20 @@ const RequestTab = ({ tab, collection, tabIndex, collectionRequestTabs, folderUi
|
||||
item = findItemInCollectionByPathname(collection, tab.pathname);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const isRequestType = tab.type === 'request'
|
||||
|| tab.type === 'http-request'
|
||||
|| tab.type === 'graphql-request'
|
||||
|| tab.type === 'grpc-request'
|
||||
|| tab.type === 'ws-request';
|
||||
|
||||
if (!isRequestType || !tab.pathname || !item?.uid || tab.uid === item.uid) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(syncTabUid({ oldUid: tab.uid, newUid: item.uid }));
|
||||
}, [dispatch, item?.uid, tab.pathname, tab.type, tab.uid]);
|
||||
|
||||
const method = useMemo(() => {
|
||||
if (!item) return;
|
||||
switch (item.type) {
|
||||
|
||||
@@ -799,3 +799,94 @@ test.describe('Snapshot: File Structure', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Snapshot: Basic Request Movement', () => {
|
||||
test('requests interactivity is also restored', async ({ launchElectronApp, createTmpDir }) => {
|
||||
const userDataPath = await createTmpDir('snap-structure');
|
||||
const colPath = await createTmpDir('col');
|
||||
|
||||
const app = await launchElectronApp({ userDataPath });
|
||||
const page = await app.firstWindow();
|
||||
await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
await test.step('Create collection and open a request', async () => {
|
||||
await createCollection(page, 'TestCol', colPath);
|
||||
await createRequest(page, 'Req1', 'TestCol', { url: 'https://echo.usebruno.com', method: 'GET' });
|
||||
await openRequest(page, 'TestCol', 'Req1', { persist: true });
|
||||
await selectRequestPaneTab(page, 'Headers');
|
||||
});
|
||||
|
||||
await test.step('Close app and inspect snapshot file', async () => {
|
||||
await page.waitForTimeout(2000);
|
||||
await closeElectronApp(app);
|
||||
});
|
||||
|
||||
await test.step('Verify request pane tabs remain interactive after restore', async () => {
|
||||
const app2 = await launchElectronApp({ userDataPath });
|
||||
const page2 = await app2.firstWindow();
|
||||
await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
const locators = buildCommonLocators(page2);
|
||||
await expect(locators.tabs.requestTab('Req1')).toBeVisible({ timeout: 15000 });
|
||||
await locators.tabs.requestTab('Req1').click({ force: true });
|
||||
|
||||
await selectRequestPaneTab(page2, 'Headers');
|
||||
await selectRequestPaneTab(page2, 'Auth');
|
||||
await selectRequestPaneTab(page2, 'Vars');
|
||||
await selectRequestPaneTab(page2, 'Tests');
|
||||
await selectRequestPaneTab(page2, 'Params');
|
||||
|
||||
await closeElectronApp(app2);
|
||||
});
|
||||
});
|
||||
|
||||
test('graphql request pane tab interactivity is restored after restart', async ({ launchElectronApp, createTmpDir }) => {
|
||||
const userDataPath = await createTmpDir('snap-graphql-interactivity');
|
||||
const colPath = await createTmpDir('col');
|
||||
|
||||
const app = await launchElectronApp({ userDataPath });
|
||||
const page = await app.firstWindow();
|
||||
await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
await test.step('Create collection and GraphQL request', async () => {
|
||||
await createCollection(page, 'TestCol', colPath);
|
||||
|
||||
const locators = buildCommonLocators(page);
|
||||
await locators.sidebar.collection('TestCol').hover();
|
||||
await locators.actions.collectionActions('TestCol').click();
|
||||
await locators.dropdown.item('New Request').click();
|
||||
|
||||
await page.getByTestId('graphql-request').click();
|
||||
await page.getByTestId('request-name').fill('ReqGraph');
|
||||
await page.getByTestId('new-request-url').locator('.CodeMirror').click();
|
||||
await page.keyboard.type('https://echo.usebruno.com/graphql');
|
||||
await locators.modal.button('Create').click();
|
||||
|
||||
await openRequest(page, 'TestCol', 'ReqGraph', { persist: true });
|
||||
await selectRequestPaneTab(page, 'Headers');
|
||||
});
|
||||
|
||||
await test.step('Close and restart app', async () => {
|
||||
await page.waitForTimeout(2000);
|
||||
await closeElectronApp(app);
|
||||
});
|
||||
|
||||
await test.step('Verify GraphQL pane tabs remain interactive', async () => {
|
||||
const app2 = await launchElectronApp({ userDataPath });
|
||||
const page2 = await app2.firstWindow();
|
||||
await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
const locators = buildCommonLocators(page2);
|
||||
await expect(locators.tabs.requestTab('ReqGraph')).toBeVisible({ timeout: 15000 });
|
||||
await locators.tabs.requestTab('ReqGraph').click({ force: true });
|
||||
|
||||
await selectRequestPaneTab(page2, 'Headers');
|
||||
await selectRequestPaneTab(page2, 'Auth');
|
||||
await selectRequestPaneTab(page2, 'Vars');
|
||||
await selectRequestPaneTab(page2, 'Tests');
|
||||
await selectRequestPaneTab(page2, 'Query');
|
||||
|
||||
await closeElectronApp(app2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
108
tests/snapshots/request-pane-interactivity.spec.ts
Normal file
108
tests/snapshots/request-pane-interactivity.spec.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { test, expect, closeElectronApp } from '../../playwright';
|
||||
import {
|
||||
createCollection,
|
||||
openRequest,
|
||||
selectRequestPaneTab
|
||||
} from '../utils/page';
|
||||
import { buildCommonLocators } from '../utils/page/locators';
|
||||
|
||||
test.describe('Snapshot: Request Pane Interactivity', () => {
|
||||
test('grpc request pane tab interactivity is restored after restart', async ({ launchElectronApp, createTmpDir }) => {
|
||||
const userDataPath = await createTmpDir('snap-grpc-interactivity');
|
||||
const colPath = await createTmpDir('col');
|
||||
|
||||
const app = await launchElectronApp({ userDataPath });
|
||||
const page = await app.firstWindow();
|
||||
await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
await test.step('Create collection and gRPC request', async () => {
|
||||
await createCollection(page, 'TestCol', colPath);
|
||||
|
||||
const locators = buildCommonLocators(page);
|
||||
await locators.sidebar.collection('TestCol').hover();
|
||||
await locators.actions.collectionActions('TestCol').click();
|
||||
await locators.dropdown.item('New Request').click();
|
||||
|
||||
await page.getByTestId('grpc-request').click();
|
||||
await page.getByTestId('request-name').fill('ReqGrpc');
|
||||
await page.getByTestId('new-request-url').locator('.CodeMirror').click();
|
||||
await page.keyboard.type('grpc://localhost:50051');
|
||||
await locators.modal.button('Create').click();
|
||||
|
||||
await openRequest(page, 'TestCol', 'ReqGrpc', { persist: true });
|
||||
await selectRequestPaneTab(page, 'Metadata');
|
||||
});
|
||||
|
||||
await test.step('Close and restart app', async () => {
|
||||
await page.waitForTimeout(2000);
|
||||
await closeElectronApp(app);
|
||||
});
|
||||
|
||||
await test.step('Verify gRPC pane tabs remain interactive', async () => {
|
||||
const app2 = await launchElectronApp({ userDataPath });
|
||||
const page2 = await app2.firstWindow();
|
||||
await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
const locators = buildCommonLocators(page2);
|
||||
await expect(locators.tabs.requestTab('ReqGrpc')).toBeVisible({ timeout: 15000 });
|
||||
await locators.tabs.requestTab('ReqGrpc').click({ force: true });
|
||||
|
||||
await selectRequestPaneTab(page2, 'Metadata');
|
||||
await selectRequestPaneTab(page2, 'Auth');
|
||||
await selectRequestPaneTab(page2, 'Docs');
|
||||
await selectRequestPaneTab(page2, 'Message');
|
||||
|
||||
await closeElectronApp(app2);
|
||||
});
|
||||
});
|
||||
|
||||
test('websocket request pane tab interactivity is restored after restart', async ({ launchElectronApp, createTmpDir }) => {
|
||||
const userDataPath = await createTmpDir('snap-ws-interactivity');
|
||||
const colPath = await createTmpDir('col');
|
||||
|
||||
const app = await launchElectronApp({ userDataPath });
|
||||
const page = await app.firstWindow();
|
||||
await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
await test.step('Create collection and WebSocket request', async () => {
|
||||
await createCollection(page, 'TestCol', colPath);
|
||||
|
||||
const locators = buildCommonLocators(page);
|
||||
await locators.sidebar.collection('TestCol').hover();
|
||||
await locators.actions.collectionActions('TestCol').click();
|
||||
await locators.dropdown.item('New Request').click();
|
||||
|
||||
await page.getByTestId('ws-request').click();
|
||||
await page.getByTestId('request-name').fill('ReqWs');
|
||||
await page.getByTestId('new-request-url').locator('.CodeMirror').click();
|
||||
await page.keyboard.type('ws://localhost:8080');
|
||||
await locators.modal.button('Create').click();
|
||||
|
||||
await openRequest(page, 'TestCol', 'ReqWs', { persist: true });
|
||||
await selectRequestPaneTab(page, 'Headers');
|
||||
});
|
||||
|
||||
await test.step('Close and restart app', async () => {
|
||||
await page.waitForTimeout(2000);
|
||||
await closeElectronApp(app);
|
||||
});
|
||||
|
||||
await test.step('Verify WebSocket pane tabs remain interactive', async () => {
|
||||
const app2 = await launchElectronApp({ userDataPath });
|
||||
const page2 = await app2.firstWindow();
|
||||
await page2.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
|
||||
|
||||
const locators = buildCommonLocators(page2);
|
||||
await expect(locators.tabs.requestTab('ReqWs')).toBeVisible({ timeout: 15000 });
|
||||
await locators.tabs.requestTab('ReqWs').click({ force: true });
|
||||
|
||||
await selectRequestPaneTab(page2, 'Headers');
|
||||
await selectRequestPaneTab(page2, 'Auth');
|
||||
await selectRequestPaneTab(page2, 'Settings');
|
||||
await selectRequestPaneTab(page2, 'Docs');
|
||||
await selectRequestPaneTab(page2, 'Message');
|
||||
|
||||
await closeElectronApp(app2);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user