Revert "feat: ws multi message (#7719)" (#7921)

This reverts commit a305b41c93.
This commit is contained in:
Sid
2026-05-06 13:59:29 +05:30
committed by GitHub
parent e92131ff8a
commit 973ca18e00
29 changed files with 302 additions and 1351 deletions

View File

@@ -1,5 +0,0 @@
{
"version": "1",
"name": "ws-multi-message",
"type": "collection"
}

View File

@@ -1,3 +0,0 @@
vars:pre-request {
variable: Variable Value
}

View File

@@ -1,29 +0,0 @@
meta {
name: ws-multi-msg
type: ws
seq: 1
}
ws {
url: ws://localhost:8081/ws/echo
body: ws
auth: inherit
}
body:ws {
name: message 1
type: json
content: '''
{
"action": "subscribe"
}
'''
}
body:ws {
name: message 2
type: text
content: '''
hello world
'''
}

View File

@@ -1,21 +0,0 @@
meta {
name: ws-single-msg
type: ws
seq: 2
}
ws {
url: ws://localhost:8081/ws/echo
body: ws
auth: inherit
}
body:ws {
name: message 1
type: json
content: '''
{
"foo": "bar"
}
'''
}

View File

@@ -1,12 +0,0 @@
{
"maximized": false,
"lastOpenedCollections": [
"{{projectRoot}}/tests/websockets/multi-message-bru/fixtures/collection"
],
"preferences": {
"onboarding": {
"hasLaunchedBefore": true,
"hasSeenWelcomeModal": true
}
}
}

View File

@@ -1,256 +0,0 @@
import { expect, test } from '../../../playwright';
import { buildWebsocketCommonLocators } from '../../utils/page/locators';
import { openRequest, saveRequest, closeAllCollections } from '../../utils/page/actions';
import { readFile, writeFile } from 'fs/promises';
import { join } from 'path';
const COLLECTION_NAME = 'ws-multi-message';
const MULTI_MSG_REQ = 'ws-multi-msg';
const SINGLE_MSG_REQ = 'ws-single-msg';
const MULTI_MSG_BRU_PATH = join(__dirname, 'fixtures/collection/ws-multi-msg.bru');
const SINGLE_MSG_BRU_PATH = join(__dirname, 'fixtures/collection/ws-single-msg.bru');
const MAX_CONNECTION_TIME = 3000;
test.describe('websocket multi-message (bru format)', () => {
let originalMultiMsgData = '';
let originalSingleMsgData = '';
test.beforeAll(async () => {
originalMultiMsgData = await readFile(MULTI_MSG_BRU_PATH, 'utf8');
originalSingleMsgData = await readFile(SINGLE_MSG_BRU_PATH, 'utf8');
});
test.afterEach(async () => {
await writeFile(MULTI_MSG_BRU_PATH, originalMultiMsgData, 'utf8');
await writeFile(SINGLE_MSG_BRU_PATH, originalSingleMsgData, 'utf8');
});
test.afterAll(async ({ pageWithUserData: page }) => {
await closeAllCollections(page);
});
test('add a new message and save', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await page.getByTestId('ws-add-message').click();
const nameInput = page.getByTestId(/^ws-message-name-input-/);
await expect(nameInput).toBeVisible();
await nameInput.selectText();
await page.keyboard.type('ping message');
await nameInput.press('Enter');
await expect(page.getByTestId(/^ws-message-label-/).filter({ hasText: 'ping message' })).toBeVisible();
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(3);
await saveRequest(page);
const bruContent = await readFile(MULTI_MSG_BRU_PATH, 'utf8');
expect(bruContent).toContain('name: ping message');
});
test('edit message content and verify persistence', async ({ pageWithUserData: page }) => {
const selectAllShortcut = process.platform === 'darwin' ? 'Meta+a' : 'Control+a';
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
// Expand the first message if not already expanded
const editorBody = page.getByTestId('ws-message-body-0');
if (!(await editorBody.isVisible())) {
await page.getByTestId('ws-message-header-0').click();
}
const editor = editorBody.locator('.CodeMirror');
await editor.click();
const textarea = editor.locator('textarea');
await textarea.focus();
await page.keyboard.press(selectAllShortcut);
await page.keyboard.insertText('{"updated": "content"}');
await saveRequest(page);
const bruContent = await readFile(SINGLE_MSG_BRU_PATH, 'utf8');
expect(bruContent).toContain('{"updated": "content"}');
});
test('messages with different types persist correctly', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
const firstHeader = page.getByTestId('ws-message-header-0');
await expect(firstHeader.locator('.selected-body-mode')).toContainText('JSON');
const secondHeader = page.getByTestId('ws-message-header-1');
await expect(secondHeader.locator('.selected-body-mode')).toContainText('TEXT');
// Change message 1 type from json to xml
await firstHeader.locator('.body-mode-selector').click();
await page.locator('.dropdown-item').filter({ hasText: 'XML' }).click();
await expect(firstHeader.locator('.selected-body-mode')).toContainText('XML');
await saveRequest(page);
const bruContent = await readFile(MULTI_MSG_BRU_PATH, 'utf8');
expect(bruContent).toContain('type: xml');
expect(bruContent).toContain('type: text');
// Re-open to verify persistence
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await expect(page.getByTestId('ws-message-header-0').locator('.selected-body-mode')).toContainText('XML');
await expect(page.getByTestId('ws-message-header-1').locator('.selected-body-mode')).toContainText('TEXT');
});
test('send selected message to active connection', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
const messageItems = locators.messages().locator('.text-ellipsis');
const beforeCount = await messageItems.count();
// Click the main send button — sends the currently selected message
await page.getByTestId('run-button').click();
// Expect at least one new message (outgoing + echo response from server)
await expect.poll(() => messageItems.count(), { timeout: MAX_CONNECTION_TIME }).toBeGreaterThan(beforeCount);
await locators.connectionControls.disconnect().click();
await expect(locators.connectionControls.connect()).toBeVisible();
});
test('first message is implicitly selected when no message is marked selected', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// ws-multi-msg.bru has two messages with no `selected: true` flag. The
// main send button should therefore dispatch the first message.
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await page.getByTestId('run-button').click();
// the first message's content ("subscribe"), and none should carry the
// second message's content ("hello world").
await expect(locators.messages().filter({ hasText: 'subscribe' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'hello world' })).toHaveCount(0);
await locators.connectionControls.disconnect().click();
});
test('selecting a different message routes run-button to that message', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// Select the second message by clicking its header
await page.getByTestId('ws-message-header-1').click();
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await page.getByTestId('run-button').click();
await expect(locators.messages().filter({ hasText: 'hello world' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'subscribe' })).toHaveCount(0);
await locators.connectionControls.disconnect().click();
});
test('per-message send button sends that specific message', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// Hover the header to reveal hover-actions, then click the second
await page.getByTestId('ws-message-header-1').hover();
await page.getByTestId('ws-send-msg-1').click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'hello world' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await locators.connectionControls.disconnect().click();
});
test('prettify json message content', async ({ pageWithUserData: page }) => {
const selectAllShortcut = process.platform === 'darwin' ? 'Meta+a' : 'Control+a';
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
// Expand the first message if not already expanded
const editorBody = page.getByTestId('ws-message-body-0');
if (!(await editorBody.isVisible())) {
await page.getByTestId('ws-message-header-0').click();
}
const editor = editorBody.locator('.CodeMirror');
await editor.click();
const textarea = editor.locator('textarea');
await textarea.focus();
await page.keyboard.press(selectAllShortcut);
await page.keyboard.insertText('{"name":"bruno","version":"1.0"}');
await page.getByTestId('ws-prettify-all').click();
// Verify prettification split single line into multiple lines
const lineNumbers = await editor.locator('.CodeMirror-linenumber').count();
expect(lineNumbers).toBeGreaterThan(1);
});
test('delete a message', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(2);
// Hover over the message header to reveal the delete button
await page.getByTestId('ws-message-header-1').hover();
await page.getByTestId('ws-delete-msg-1').click();
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(1);
await saveRequest(page);
const bruContent = await readFile(MULTI_MSG_BRU_PATH, 'utf8');
const bodyWsCount = (bruContent.match(/body:ws/g) || []).length;
expect(bodyWsCount).toBe(1);
});
test('rename a message via double-click', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
const messageLabel = page.getByTestId('ws-message-label-0');
await messageLabel.dblclick();
const nameInput = page.getByTestId('ws-message-name-input-0');
await expect(nameInput).toBeVisible();
await nameInput.selectText();
await page.keyboard.type('subscribe request');
await nameInput.press('Enter');
await expect(page.getByTestId('ws-message-label-0').filter({ hasText: 'subscribe request' })).toBeVisible();
await saveRequest(page);
const bruContent = await readFile(SINGLE_MSG_BRU_PATH, 'utf8');
expect(bruContent).toContain('name: subscribe request');
});
});

View File

@@ -1,6 +0,0 @@
opencollection: '1.0.0'
info:
name: ws-multi-message-yml
bundled: false

View File

@@ -1,24 +0,0 @@
info:
name: ws-multi-msg
type: websocket
seq: 1
websocket:
url: ws://localhost:8081/ws/echo
message:
- title: message 1
message:
type: json
data: |-
{
"action": "subscribe"
}
- title: message 2
message:
type: text
data: hello world
auth: inherit
settings:
timeout: 0
keepAliveInterval: 0

View File

@@ -1,18 +0,0 @@
info:
name: ws-single-msg
type: websocket
seq: 2
websocket:
url: ws://localhost:8081/ws/echo
message:
type: json
data: |-
{
"foo": "bar"
}
auth: inherit
settings:
timeout: 0
keepAliveInterval: 0

View File

@@ -1,12 +0,0 @@
{
"maximized": false,
"lastOpenedCollections": [
"{{projectRoot}}/tests/websockets/multi-message-yml/fixtures/collection"
],
"preferences": {
"onboarding": {
"hasLaunchedBefore": true,
"hasSeenWelcomeModal": true
}
}
}

View File

@@ -1,294 +0,0 @@
import { expect, test } from '../../../playwright';
import { buildWebsocketCommonLocators } from '../../utils/page/locators';
import { openRequest, saveRequest, closeAllCollections } from '../../utils/page/actions';
import { readFile, writeFile } from 'fs/promises';
import { join } from 'path';
const COLLECTION_NAME = 'ws-multi-message-yml';
const MULTI_MSG_REQ = 'ws-multi-msg';
const SINGLE_MSG_REQ = 'ws-single-msg';
const MULTI_MSG_YML_PATH = join(__dirname, 'fixtures/collection/ws-multi-msg.yml');
const SINGLE_MSG_YML_PATH = join(__dirname, 'fixtures/collection/ws-single-msg.yml');
const MAX_CONNECTION_TIME = 3000;
test.describe('websocket multi-message (yml format)', () => {
let originalMultiMsgData = '';
let originalSingleMsgData = '';
test.beforeAll(async () => {
originalMultiMsgData = await readFile(MULTI_MSG_YML_PATH, 'utf8');
originalSingleMsgData = await readFile(SINGLE_MSG_YML_PATH, 'utf8');
});
test.afterEach(async () => {
await writeFile(MULTI_MSG_YML_PATH, originalMultiMsgData, 'utf8');
await writeFile(SINGLE_MSG_YML_PATH, originalSingleMsgData, 'utf8');
});
test.afterAll(async ({ pageWithUserData: page }) => {
await closeAllCollections(page);
});
test('backward compatibility: old single-message format loads correctly', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
// The old format (message: { type, data }) should load as a single accordion
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(1);
// Expand the first message if not already expanded
if (!(await page.getByTestId('ws-message-body-0').isVisible())) {
await page.getByTestId('ws-message-header-0').click();
}
await expect(page.getByTestId('ws-message-body-0')).toBeVisible();
// Verify the type is correctly read from the old format
await expect(page.getByTestId('ws-message-header-0').locator('.selected-body-mode')).toContainText('JSON');
// Add a second message to trigger format migration
await page.getByTestId('ws-add-message').click();
const nameInput = page.getByTestId(/^ws-message-name-input-/);
await expect(nameInput).toBeVisible();
await nameInput.selectText();
await page.keyboard.type('new message');
await nameInput.press('Enter');
await saveRequest(page);
// Verify the yml file now uses the array format (WebSocketMessageVariant[])
const ymlContent = await readFile(SINGLE_MSG_YML_PATH, 'utf8');
expect(ymlContent).toContain('- title:');
expect(ymlContent).toContain('new message');
// Re-open to verify it still loads correctly after format migration
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(2);
});
test('add a new message and save', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await page.getByTestId('ws-add-message').click();
const nameInput = page.getByTestId(/^ws-message-name-input-/);
await expect(nameInput).toBeVisible();
await nameInput.selectText();
await page.keyboard.type('ping message');
await nameInput.press('Enter');
await expect(page.getByTestId(/^ws-message-label-/).filter({ hasText: 'ping message' })).toBeVisible();
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(3);
await saveRequest(page);
const ymlContent = await readFile(MULTI_MSG_YML_PATH, 'utf8');
expect(ymlContent).toContain('ping message');
});
test('edit message content and verify persistence', async ({ pageWithUserData: page }) => {
const selectAllShortcut = process.platform === 'darwin' ? 'Meta+a' : 'Control+a';
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
// Expand the first message if not already expanded
const editorBody = page.getByTestId('ws-message-body-0');
if (!(await editorBody.isVisible())) {
await page.getByTestId('ws-message-header-0').click();
}
const editor = editorBody.locator('.CodeMirror');
await editor.click();
const textarea = editor.locator('textarea');
await textarea.focus();
await page.keyboard.press(selectAllShortcut);
await page.keyboard.insertText('{"updated": "content"}');
await saveRequest(page);
const ymlContent = await readFile(SINGLE_MSG_YML_PATH, 'utf8');
expect(ymlContent).toContain('{"updated": "content"}');
});
test('messages with different types persist correctly', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
const firstHeader = page.getByTestId('ws-message-header-0');
await expect(firstHeader.locator('.selected-body-mode')).toContainText('JSON');
const secondHeader = page.getByTestId('ws-message-header-1');
await expect(secondHeader.locator('.selected-body-mode')).toContainText('TEXT');
// Change message 1 type from json to xml
await firstHeader.locator('.body-mode-selector').click();
await page.locator('.dropdown-item').filter({ hasText: 'XML' }).click();
await expect(firstHeader.locator('.selected-body-mode')).toContainText('XML');
await saveRequest(page);
const ymlContent = await readFile(MULTI_MSG_YML_PATH, 'utf8');
expect(ymlContent).toContain('type: xml');
expect(ymlContent).toContain('type: text');
// Re-open to verify persistence
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await expect(page.getByTestId('ws-message-header-0').locator('.selected-body-mode')).toContainText('XML');
await expect(page.getByTestId('ws-message-header-1').locator('.selected-body-mode')).toContainText('TEXT');
});
test('send selected message to active connection', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
const messageItems = locators.messages().locator('.text-ellipsis');
const beforeCount = await messageItems.count();
// Click the main send button — sends the currently selected message
await page.getByTestId('run-button').click();
// Expect at least one new message (outgoing + echo response from server)
await expect.poll(() => messageItems.count(), { timeout: MAX_CONNECTION_TIME }).toBeGreaterThan(beforeCount);
await locators.connectionControls.disconnect().click();
await expect(locators.connectionControls.connect()).toBeVisible();
});
test('first message is implicitly selected when no message is marked selected', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// ws-multi-msg.yml has two messages with no `selected: true` flag. The
// main send button should therefore dispatch the first message.
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await page.getByTestId('run-button').click();
// the first message's content ("subscribe"), and none should carry the
// second message's content ("hello world").
await expect(locators.messages().filter({ hasText: 'subscribe' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'hello world' })).toHaveCount(0);
await locators.connectionControls.disconnect().click();
});
test('selecting a different message routes run-button to that message', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// Select the second message by clicking its header
await page.getByTestId('ws-message-header-1').click();
await locators.connectionControls.connect().click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await page.getByTestId('run-button').click();
await expect(locators.messages().filter({ hasText: 'hello world' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'subscribe' })).toHaveCount(0);
await locators.connectionControls.disconnect().click();
});
test('per-message send button sends that specific message', async ({ pageWithUserData: page }) => {
const locators = buildWebsocketCommonLocators(page);
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
// Hover the header to reveal hover-actions, then click the second
// message's send button
await page.getByTestId('ws-message-header-1').hover();
await page.getByTestId('ws-send-msg-1').click();
await expect(locators.connectionControls.disconnect()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await expect(locators.messages().filter({ hasText: 'hello world' }).first()).toBeAttached({
timeout: MAX_CONNECTION_TIME
});
await locators.connectionControls.disconnect().click();
});
test('prettify json message content', async ({ pageWithUserData: page }) => {
const selectAllShortcut = process.platform === 'darwin' ? 'Meta+a' : 'Control+a';
await openRequest(page, COLLECTION_NAME, SINGLE_MSG_REQ);
// Expand the first message if not already expanded
const editorBody = page.getByTestId('ws-message-body-0');
if (!(await editorBody.isVisible())) {
await page.getByTestId('ws-message-header-0').click();
}
const editor = editorBody.locator('.CodeMirror');
await editor.click();
const textarea = editor.locator('textarea');
await textarea.focus();
await page.keyboard.press(selectAllShortcut);
await page.keyboard.insertText('{"name":"bruno","version":"1.0"}');
await page.getByTestId('ws-prettify-all').click();
// Verify prettification split single line into multiple lines
const lineNumbers = await editor.locator('.CodeMirror-linenumber').count();
expect(lineNumbers).toBeGreaterThan(1);
});
test('delete a message', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(2);
// Hover over the message header to reveal the delete button
await page.getByTestId('ws-message-header-1').hover();
await page.getByTestId('ws-delete-msg-1').click();
await expect(page.getByTestId(/^ws-message-header-/)).toHaveCount(1);
await saveRequest(page);
const ymlContent = await readFile(MULTI_MSG_YML_PATH, 'utf8');
const titleCount = (ymlContent.match(/- title:/g) || []).length;
expect(titleCount).toBeLessThanOrEqual(1);
});
test('rename a message via double-click', async ({ pageWithUserData: page }) => {
await openRequest(page, COLLECTION_NAME, MULTI_MSG_REQ);
const messageLabel = page.getByTestId('ws-message-label-0');
await messageLabel.dblclick();
const nameInput = page.getByTestId('ws-message-name-input-0');
await expect(nameInput).toBeVisible();
await nameInput.selectText();
await page.keyboard.type('subscribe request');
await nameInput.press('Enter');
await expect(page.getByTestId('ws-message-label-0').filter({ hasText: 'subscribe request' })).toBeVisible();
await saveRequest(page);
const ymlContent = await readFile(MULTI_MSG_YML_PATH, 'utf8');
expect(ymlContent).toContain('subscribe request');
});
});