mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-11 09:51:30 +00:00
chore: fixes
This commit is contained in:
@@ -533,24 +533,50 @@ test.describe('CodeEditor — undo (Cmd-Z) survives a tab switch', () => {
|
||||
await selectBodyMode(page, 'JSON');
|
||||
await setBodyContent(page, SAMPLE_BODY);
|
||||
|
||||
// Insert all three sentinels in one `evaluate` (no `await` between calls):
|
||||
// Insert all three sentinels with three distinct CM history entries
|
||||
// (preserved by the `*`-prefixed origins) while ensuring the React
|
||||
// wrapper sees only ONE onChange. The wrapper's `_onEdit` listener
|
||||
// dispatches `updateRequestBody` on every `change` event; on slow
|
||||
// runners three rapid dispatches don't always batch, and an
|
||||
// intermediate re-render with a stale `props.value` can trigger
|
||||
// `componentDidUpdate`'s `setValue(props.value)` path, wiping a
|
||||
// just-inserted sentinel. We detach `change` listeners for the
|
||||
// duration of the three `replaceRange`s, restore them after, then
|
||||
// fire ONE synthetic change so the wrapper dispatches once with the
|
||||
// final value — leaving editor content and redux state in sync before
|
||||
// any downstream tab-switch reads from `props.value`.
|
||||
await cmFor(page, page.locator('.request-pane')).evaluate((el) => {
|
||||
const editor = (el as any).CodeMirror;
|
||||
editor.focus();
|
||||
const doc = editor.getDoc();
|
||||
const append = (sentinel: string, originSuffix: string) => {
|
||||
const lastLine = doc.lastLine();
|
||||
const lastLineLen = doc.getLine(lastLine).length;
|
||||
doc.replaceRange(
|
||||
`\n${sentinel}`,
|
||||
{ line: lastLine, ch: lastLineLen },
|
||||
undefined,
|
||||
`*${originSuffix}`
|
||||
);
|
||||
};
|
||||
append('// SENTINEL_ONE', 'sentinel-1');
|
||||
append('// SENTINEL_TWO', 'sentinel-2');
|
||||
append('// SENTINEL_THREE', 'sentinel-3');
|
||||
// CM5 stores listeners in an internal `_handlers` map on the editor.
|
||||
// Save and clear the `change` slot, do the inserts, restore, then
|
||||
// fire one synthetic change to flush the final value through onEdit.
|
||||
const handlersSlot = editor._handlers || (editor._handlers = {});
|
||||
const savedChange = (handlersSlot.change || []).slice();
|
||||
handlersSlot.change = [];
|
||||
try {
|
||||
const append = (sentinel: string, originSuffix: string) => {
|
||||
const lastLine = doc.lastLine();
|
||||
const lastLineLen = doc.getLine(lastLine).length;
|
||||
doc.replaceRange(
|
||||
`\n${sentinel}`,
|
||||
{ line: lastLine, ch: lastLineLen },
|
||||
undefined,
|
||||
`*${originSuffix}`
|
||||
);
|
||||
};
|
||||
append('// SENTINEL_ONE', 'sentinel-1');
|
||||
append('// SENTINEL_TWO', 'sentinel-2');
|
||||
append('// SENTINEL_THREE', 'sentinel-3');
|
||||
} finally {
|
||||
handlersSlot.change = savedChange;
|
||||
}
|
||||
// `_onEdit` only reads `editor.getValue()`; the change descriptor
|
||||
// arg is unused, so passing null is safe.
|
||||
savedChange.forEach((handler: (cm: unknown, change: unknown) => void) => {
|
||||
handler(editor, null);
|
||||
});
|
||||
});
|
||||
|
||||
const cm = cmFor(page, page.locator('.request-pane'));
|
||||
|
||||
@@ -839,6 +839,12 @@ const setResponsePreviewMode = async (page: Page, mode: 'editor' | 'preview') =>
|
||||
const dropdown = page.getByTestId('format-response-tab-dropdown');
|
||||
await dropdown.waitFor({ state: 'visible', timeout: 5000 });
|
||||
const toggle = page.getByTestId('preview-response-tab');
|
||||
// The toggle's `title` reflects current state (`Turn off|on Preview Mode`).
|
||||
// Wait until it's actually one of those values — `getAttribute` returns
|
||||
// `null` if read before React flushes props to DOM, which would mislead
|
||||
// the state check below into thinking we're already in editor mode and
|
||||
// skip the toggle click, leaving us stuck in preview.
|
||||
await expect(toggle).toHaveAttribute('title', /^Turn (off|on) Preview Mode$/);
|
||||
const isPreview = (await toggle.getAttribute('title')) === 'Turn off Preview Mode';
|
||||
const wantPreview = mode === 'preview';
|
||||
if (isPreview !== wantPreview) {
|
||||
@@ -848,6 +854,10 @@ const setResponsePreviewMode = async (page: Page, mode: 'editor' | 'preview') =>
|
||||
// interactions (format selection, asserts) aren't shadowed by it.
|
||||
await responseFormatTab.click();
|
||||
}
|
||||
// Confirm the dropdown actually closed before returning. Otherwise a
|
||||
// subsequent format-selector click can land in a half-open state and
|
||||
// miss the next interaction.
|
||||
await dropdown.waitFor({ state: 'hidden', timeout: 5000 });
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user