mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-15 03:41:28 +00:00
fix: send-request shortcut (#7853)
* fix: send-request shortcut * fix: test cases --------- Co-authored-by: shubh-bruno <shubh-bruno@shubh-bruno.local> Co-authored-by: phubadeepjs <ID+phubadeepjs@users.noreply.github.com>
This commit is contained in:
@@ -50,6 +50,13 @@ export default class CodeEditor extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
const variables = getAllVariables(this.props.collection, this.props.item);
|
||||
const runShortcut = () => {
|
||||
if (this.props.onRun) {
|
||||
this.props.onRun();
|
||||
return;
|
||||
}
|
||||
return CodeMirror.Pass;
|
||||
};
|
||||
|
||||
const editor = (this.editor = CodeMirror(this._node, {
|
||||
value: this.props.value || '',
|
||||
@@ -86,6 +93,8 @@ export default class CodeEditor extends React.Component {
|
||||
},
|
||||
'Cmd-H': this.props.readOnly ? false : 'replace',
|
||||
'Ctrl-H': this.props.readOnly ? false : 'replace',
|
||||
'Cmd-Enter': runShortcut,
|
||||
'Ctrl-Enter': runShortcut,
|
||||
'Tab': function (cm) {
|
||||
cm.getSelection().includes('\n') || editor.getLine(cm.getCursor().line) == cm.getSelection()
|
||||
? cm.execCommand('indentMore')
|
||||
|
||||
@@ -30,6 +30,13 @@ class MultiLineEditor extends Component {
|
||||
// Initialize CodeMirror as a single line editor
|
||||
/** @type {import("codemirror").Editor} */
|
||||
const variables = getAllVariables(this.props.collection, this.props.item);
|
||||
const runShortcut = () => {
|
||||
if (this.props.onRun) {
|
||||
this.props.onRun();
|
||||
return;
|
||||
}
|
||||
return CodeMirror.Pass;
|
||||
};
|
||||
|
||||
this.editor = CodeMirror(this.editorRef.current, {
|
||||
lineWrapping: false,
|
||||
@@ -47,6 +54,8 @@ class MultiLineEditor extends Component {
|
||||
extraKeys: {
|
||||
'Cmd-F': () => {},
|
||||
'Ctrl-F': () => {},
|
||||
'Cmd-Enter': runShortcut,
|
||||
'Ctrl-Enter': runShortcut,
|
||||
// Tabbing disabled to make tabindex work
|
||||
'Tab': false,
|
||||
'Shift-Tab': false
|
||||
|
||||
@@ -61,7 +61,9 @@ const RequestTabPanel = () => {
|
||||
const isConsoleOpen = useSelector((state) => state.logs.isConsoleOpen);
|
||||
|
||||
const isRequestTab = focusedTab && ['request', 'grpc-request', 'ws-request', 'graphql-request'].includes(focusedTab.type);
|
||||
useKeybinding('sendRequest', () => {
|
||||
useKeybinding('sendRequest', (e) => {
|
||||
e?.preventDefault?.();
|
||||
e?.stopPropagation?.();
|
||||
handleRun();
|
||||
return false;
|
||||
}, { enabled: !!isRequestTab, deps: [isRequestTab] });
|
||||
|
||||
@@ -5,7 +5,8 @@ import {
|
||||
openRequest as openRequestBase,
|
||||
closeAllCollections,
|
||||
createFolder,
|
||||
openCollection
|
||||
openCollection,
|
||||
selectRequestPaneTab
|
||||
} from '../utils/page';
|
||||
|
||||
const modifier = process.platform === 'darwin' ? 'Meta' : 'Control';
|
||||
@@ -56,7 +57,7 @@ const closePreferencesTab = async (page: Page) => {
|
||||
const prefTab = page.locator('.request-tab').filter({ hasText: 'Preferences' });
|
||||
await prefTab.hover();
|
||||
await prefTab.getByTestId('request-tab-close-icon').click({ force: true });
|
||||
await expect(prefTab).not.toBeVisible({ timeout: 2000 });
|
||||
await expect(prefTab).not.toBeVisible({ timeout: 8000 });
|
||||
};
|
||||
|
||||
const closeTabByName = async (page: any, name: string | RegExp) => {
|
||||
@@ -1738,4 +1739,275 @@ test.describe('Shortcut Keys - BOUND_ACTIONS', () => {
|
||||
await page.getByTestId('reset-all-keybindings-btn').click({ timeout: 2000 });
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('REQUESTS', () => {
|
||||
test.describe('SHORTCUT: Send Request from CodeEditor (Cmd/Ctrl+Enter)', () => {
|
||||
test('sends request when cursor is in JSON body editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
// Create a POST request in the shared collection pointing to the echo server
|
||||
await createRequest(page, 'cmd-enter-req-body', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'cmd-enter-req-body', { persist: true });
|
||||
|
||||
// Open Body tab and select JSON mode
|
||||
await selectRequestPaneTab(page, 'Body');
|
||||
await page.getByTestId('request-body-mode-selector').click();
|
||||
await page.locator('.dropdown-item').filter({ hasText: /^JSON$/ }).click();
|
||||
|
||||
// Focus the body code editor and type JSON
|
||||
const bodyEditor = page.getByTestId('request-body-editor').locator('.CodeMirror');
|
||||
await bodyEditor.click();
|
||||
await page.keyboard.type('{"name": "Bruno", "version": 2, "tags": ["api", "client", "http"], "active": true, "meta": {"author": "user", "created": "2025-01-01", "updated": "2025-06-01"}, "counts": {"requests": 42, "collections": 7}}');
|
||||
await expect(page.getByTestId('request-body-editor')).toContainText('"name": "Bruno"', { timeout: 5000 });
|
||||
|
||||
// Cursor is still in the body CodeMirror — press Cmd/Ctrl+Enter to send
|
||||
await page.keyboard.press(`${modifier}+Enter`);
|
||||
|
||||
// Verify a 200 response came back
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
});
|
||||
|
||||
test('sends request when cursor is in response body editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
await createRequest(page, 'cmd-enter-req-resp', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'cmd-enter-req-resp', { persist: true });
|
||||
|
||||
await selectRequestPaneTab(page, 'Body');
|
||||
await page.getByTestId('request-body-mode-selector').click();
|
||||
await page.locator('.dropdown-item').filter({ hasText: /^JSON$/ }).click();
|
||||
|
||||
const bodyEditor = page.getByTestId('request-body-editor').locator('.CodeMirror');
|
||||
await bodyEditor.click();
|
||||
await page.keyboard.type('{"name": "Bruno", "version": 2, "tags": ["api", "client", "http"], "active": true, "meta": {"author": "user", "created": "2025-01-01", "updated": "2025-06-01"}, "counts": {"requests": 42, "collections": 7}}');
|
||||
await expect(page.getByTestId('request-body-editor')).toContainText('"name": "Bruno"', { timeout: 5000 });
|
||||
|
||||
// First send to populate response
|
||||
await page.keyboard.press(`${modifier}+Enter`);
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
|
||||
// Focus cursor inside the response body CodeMirror
|
||||
const responseEditor = page.getByTestId('response-preview-container').locator('.CodeMirror').first();
|
||||
await responseEditor.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await responseEditor.click();
|
||||
|
||||
// Press Cmd/Ctrl+Enter again — should re-send the request
|
||||
await page.keyboard.press(`${modifier}+Enter`);
|
||||
|
||||
// Verify a 200 response came back (no error, status stays/refreshes to 200)
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
});
|
||||
|
||||
test('sends request when cursor is in pre-request Vars value editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
await createRequest(page, 'cmd-enter-req-vars', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'cmd-enter-req-vars', { persist: true });
|
||||
|
||||
// Open Vars tab — request Vars has a Pre Request section as the first table
|
||||
await selectRequestPaneTab(page, 'Vars');
|
||||
|
||||
// Fill the first var row: name=var-1
|
||||
const varsTable = page.getByTestId('request-pane').locator('table').first();
|
||||
const firstRow = varsTable.locator('tbody tr').first();
|
||||
const nameInput = firstRow.locator('input[type="text"]').first();
|
||||
await nameInput.click();
|
||||
await nameInput.fill('var-1');
|
||||
|
||||
// Click the value CodeMirror editor and type a multi-line value
|
||||
const valueEditor = firstRow.locator('.CodeMirror').first();
|
||||
await valueEditor.click();
|
||||
await page.keyboard.type('val-1');
|
||||
await page.keyboard.press('Enter'); // insert newline in value editor
|
||||
await page.keyboard.type('val-2');
|
||||
|
||||
// Cursor is still in the value CodeMirror — press Cmd/Ctrl+Enter to send
|
||||
// (should NOT insert a newline; should fire sendRequest)
|
||||
await page.keyboard.press(`${modifier}+Enter`);
|
||||
|
||||
// Verify a 200 response came back
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('SHORTCUT: Send Request from CodeEditor (customized Shift+Enter)', () => {
|
||||
test('customized Shift+Enter sends request when cursor is in JSON body editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
// Remap sendRequest to Shift+Enter
|
||||
await openKeybindingsTab(page);
|
||||
const row = page.getByTestId('keybinding-row-sendRequest');
|
||||
await row.hover();
|
||||
await page.getByTestId('keybinding-edit-sendRequest').click();
|
||||
await expect(page.getByTestId('keybinding-input-sendRequest')).toBeVisible({ timeout: 2000 });
|
||||
|
||||
await page.keyboard.down('Backspace');
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.down('Enter');
|
||||
await page.keyboard.up('Enter');
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
// await closePreferencesTab(page);
|
||||
// Create a POST request in the shared collection pointing to the echo server
|
||||
await createRequest(page, 'shift-enter-req-body', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'shift-enter-req-body', { persist: true });
|
||||
|
||||
// Open Body tab and select JSON mode
|
||||
await selectRequestPaneTab(page, 'Body');
|
||||
await page.getByTestId('request-body-mode-selector').click();
|
||||
await page.locator('.dropdown-item').filter({ hasText: /^JSON$/ }).click();
|
||||
|
||||
const bodyEditor = page.getByTestId('request-body-editor').locator('.CodeMirror');
|
||||
await bodyEditor.click();
|
||||
await page.keyboard.type('{"name": "Bruno", "version": 2, "tags": ["api", "client", "http"], "active": true, "meta": {"author": "user", "created": "2025-01-01", "updated": "2025-06-01"}, "counts": {"requests": 42, "collections": 7}}');
|
||||
await expect(page.getByTestId('request-body-editor')).toContainText('"name": "Bruno"', { timeout: 5000 });
|
||||
|
||||
// Cursor is still in the body CodeMirror — press Shift+Enter (customized) to send
|
||||
await page.keyboard.press('Shift+Enter');
|
||||
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
|
||||
// Reset Default
|
||||
await openKeybindingsTab(page);
|
||||
await page.getByTestId('reset-all-keybindings-btn').click({ timeout: 2000 });
|
||||
});
|
||||
|
||||
test('customized Shift+Enter sends request when cursor is in response body editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
// Remap sendRequest to Shift+Enter
|
||||
await openKeybindingsTab(page);
|
||||
const row = page.getByTestId('keybinding-row-sendRequest');
|
||||
await row.hover();
|
||||
await page.getByTestId('keybinding-edit-sendRequest').click();
|
||||
await expect(page.getByTestId('keybinding-input-sendRequest')).toBeVisible({ timeout: 2000 });
|
||||
|
||||
await page.keyboard.down('Backspace');
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.down('Enter');
|
||||
await page.keyboard.up('Enter');
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
// await closePreferencesTab(page);
|
||||
await createRequest(page, 'shift-enter-req-resp', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'shift-enter-req-resp', { persist: true });
|
||||
|
||||
await selectRequestPaneTab(page, 'Body');
|
||||
await page.getByTestId('request-body-mode-selector').click();
|
||||
await page.locator('.dropdown-item').filter({ hasText: /^JSON$/ }).click();
|
||||
|
||||
const bodyEditor = page.getByTestId('request-body-editor').locator('.CodeMirror');
|
||||
await bodyEditor.click();
|
||||
await page.keyboard.type('{"name": "Bruno", "version": 2, "tags": ["api", "client", "http"], "active": true, "meta": {"author": "user", "created": "2025-01-01", "updated": "2025-06-01"}, "counts": {"requests": 42, "collections": 7}}');
|
||||
await expect(page.getByTestId('request-body-editor')).toContainText('"name": "Bruno"', { timeout: 5000 });
|
||||
|
||||
// First send with Shift+Enter to populate response
|
||||
await page.keyboard.press('Shift+Enter');
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
|
||||
// Focus cursor inside the response body CodeMirror
|
||||
const responseEditor = page.getByTestId('response-preview-container').locator('.CodeMirror').first();
|
||||
await responseEditor.waitFor({ state: 'visible', timeout: 5000 });
|
||||
await responseEditor.click();
|
||||
|
||||
// Press Shift+Enter again — should re-send the request
|
||||
await page.keyboard.press('Shift+Enter');
|
||||
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
|
||||
// Reset Default
|
||||
await openKeybindingsTab(page);
|
||||
await page.getByTestId('reset-all-keybindings-btn').click({ timeout: 2000 });
|
||||
});
|
||||
|
||||
test('customized Shift+Enter sends request when cursor is in pre-request Vars value editor', async ({ page }) => {
|
||||
// Close existing tabs
|
||||
await page.keyboard.down('Alt');
|
||||
await page.keyboard.down('KeyY');
|
||||
await page.keyboard.up('KeyY');
|
||||
await page.keyboard.up('Alt');
|
||||
|
||||
// Remap sendRequest to Shift+Enter
|
||||
await openKeybindingsTab(page);
|
||||
const row = page.getByTestId('keybinding-row-sendRequest');
|
||||
await row.hover();
|
||||
await page.getByTestId('keybinding-edit-sendRequest').click();
|
||||
await expect(page.getByTestId('keybinding-input-sendRequest')).toBeVisible({ timeout: 2000 });
|
||||
|
||||
await page.keyboard.down('Backspace');
|
||||
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.down('Enter');
|
||||
await page.keyboard.up('Enter');
|
||||
await page.keyboard.up('Shift');
|
||||
|
||||
// await closePreferencesTab(page);
|
||||
await createRequest(page, 'shift-enter-req-vars', 'kb-collection', {
|
||||
url: 'https://echo.usebruno.com',
|
||||
method: 'POST'
|
||||
});
|
||||
await openRequest(page, 'kb-collection', 'shift-enter-req-vars', { persist: true });
|
||||
|
||||
await selectRequestPaneTab(page, 'Vars');
|
||||
|
||||
const varsTable = page.getByTestId('request-pane').locator('table').first();
|
||||
const firstRow = varsTable.locator('tbody tr').first();
|
||||
const nameInput = firstRow.locator('input[type="text"]').first();
|
||||
await nameInput.click();
|
||||
await nameInput.fill('var-1');
|
||||
|
||||
const valueEditor = firstRow.locator('.CodeMirror').first();
|
||||
await valueEditor.click();
|
||||
await page.keyboard.type('val-1');
|
||||
await page.keyboard.press('Enter'); // insert newline in value editor
|
||||
await page.keyboard.type('val-2');
|
||||
|
||||
// Cursor is still in the value CodeMirror — press Shift+Enter (customized) to send
|
||||
await page.keyboard.press('Shift+Enter');
|
||||
|
||||
await expect(page.getByTestId('response-status-code')).toContainText('200', { timeout: 15000 });
|
||||
|
||||
// Reset Default
|
||||
await openKeybindingsTab(page);
|
||||
await page.getByTestId('reset-all-keybindings-btn').click({ timeout: 2000 });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user