Skip to content

feat(playground): response body formatting, preview, and format selector (BRU-3764) - #8

Merged
arpit-bruno merged 21 commits into
usebruno:mainfrom
vasharma05-bruno:bru-3764-response-formatter
Jul 29, 2026
Merged

feat(playground): response body formatting, preview, and format selector (BRU-3764)#8
arpit-bruno merged 21 commits into
usebruno:mainfrom
vasharma05-bruno:bru-3764-response-formatter

Conversation

@vasharma05-bruno

@vasharma05-bruno vasharma05-bruno commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What

Wires up the response-format flow in the docs playground so the response body is formatted, previewable, and selectable by format — porting the mature behaviour from the Bruno Electron app, adapted for a browser/SSR environment.

Changes

  • Editor formatting — the editor body is now produced per-format via formatResponse (JSON/XML/HTML/JS prettify, hex dump, base64 passthrough, raw decode) instead of a naive JSON.stringify. Monaco is only ever handed a real grammar (raw/hex/base64plaintext). This wires in the previously-orphaned utils/dataFormatter.ts.
  • Preview mode — extracted the inline preview-mode mapping into a pure previewMode.ts (formatToPreviewMode) and reconciled its spec.
  • Binary-aware format optionsgetResponseFormatOptions hides the structured formats (JSON/HTML/XML/JS) for binary responses (image/video/audio/pdf/zip); SVG stays text.
  • Sticky preview toggle — a manual Preview toggle now survives same-response re-renders; a genuine content-type change still re-derives the default. A stale format choice that no longer applies to the current body falls back to the detected default.

Tests

  • Unit (Vitest): added dataFormatter hex/base64 cases and getResponseFormatOptions coverage; reconciled QueryResultPreview.spec.tsx (was red on the branch).
  • E2E (Playwright): new response-body spec + response-pane page object covering format switching and binary option-hiding.

Screenshots

image image

Responses greater than 10MB

image

HTML

image

JavaScript

image

XML

image image

Video

image image

Wire the response-format flow in the docs playground:
- Format the editor body per format via formatResponse (JSON/XML/HTML/JS
  prettify, hex dump, base64 passthrough, raw), and feed Monaco only real
  grammars (raw/hex/base64 -> plaintext).
- Extract the preview-mode mapping into a pure previewMode helper and
  reconcile its spec.
- Hide structured formats for binary responses (image/video/audio/pdf/zip;
  SVG stays text) via getResponseFormatOptions.
- Keep the preview toggle sticky across same-response re-renders, and ignore
  a stale format choice that no longer applies to the current body.

Adds unit coverage (dataFormatter hex/base64, getResponseFormatOptions) and
Playwright coverage (format switching + binary option hiding).
…rmatting

Follow-up polish to the response-format flow:
- Resolve content-type once per render in ResponsePane and thread it into
  useResponseFormatter and ResponseBodyTab, replacing three independent
  sniff+header-parse call sites.
- Skip formatResponse (a full base64 decode) while the preview view is
  active, and narrow formatResponse to return string (drops the call-site
  coercion).
- Single-source the structured/byte format-id arrays from response.ts.
- Extract the repeated large-response fallback in dataFormatter into one
  helper; drop a stray console.log.
- Replace the fragile contentType.replace(/\;(.*)/) data-URI parse with
  split(';') (also clears a no-useless-escape lint error); remove a dead
  PreviewMode re-export, an unused import, and a no-op Omit/cast.
@vasharma05-bruno
vasharma05-bruno marked this pull request as draft July 27, 2026 09:03
Behavior-preserving improvements to the response-detection utilities in
utils/response.ts: hoist the per-call-recompiled content-type regexes and the
getDefaultResponseFormat rules table to module scope, and add unit tests
locking getContentType, getDefaultResponseFormat, detectContentTypeFromBuffer,
and detectContentTypeFromBase64 behavior.
@vasharma05-bruno
vasharma05-bruno force-pushed the bru-3764-response-formatter branch from e6fc6ad to 896b811 Compare July 27, 2026 09:08
Remove restatement/banner/narration comments (mostly carried over with the
bruno-app port) from response.ts, dataFormatter.ts, and ResponsePane.tsx.
Rationale/invariant/provenance comments are kept.
Mirror bruno-app: when a response body exceeds 10 MB, show a
LargeResponseWarning (current size + a View action) instead of rendering the
body, and skip the full base64 decode/formatting until the user reveals it.
The reveal resets when the response changes.
@vasharma05-bruno
vasharma05-bruno marked this pull request as ready for review July 27, 2026 13:46
Comment thread packages/bruno-api-docs/package.json
Comment thread packages/bruno-api-docs/src/utils/dataFormatter.ts
Comment thread packages/bruno-api-docs/src/runner/RequestExecutor.ts
Comment thread packages/bruno-api-docs/package.json
- QueryResultPreview.spec: correct relative import depth (../../../, not ../../../../)
- runner/index.spec: provide arrayBuffer() on fetch mocks to match the new
  Response parsing contract (base64Data via response.arrayBuffer())
- response-body e2e: intercept the real request URL (**/api/users**) instead of
  a nonexistent /__proxy; reach the Headers tab via the response-tab overflow menu
- response-pane POM: normalise Monaco's non-breaking spaces in bodyText()
…arse time

Addresses review feedback about eagerly base64-encoding every response body.

- RequestExecutor.parseResponse: take size from arrayBuffer.byteLength (no Buffer
  copy just to measure); sniff the content type from the bytes once and store it as
  `detectedContentType`; skip base64 for reconstructable text (plain/SVG string
  bodies) and for oversized (>10MB) bodies. Binary, JSON, and non-ASCII/ambiguous
  bodies keep base64 — previews and precise formatting need the faithful bytes.
- response.ts: extract byte-based detectContentTypeFromBytes and route
  detectContentTypeFromBase64 through it; export isByteFormatContentType; drop two
  dead imports.
- useInitialResponseFormat: prefer response.detectedContentType (base64 sniff fallback).
- dataFormatter.formatResponse: format from `data` when no base64 buffer is present and
  derive hex/base64 from the text body; keep fast-json-format for JSON (it preserves
  bigint precision — not redundant with safeStringifyJSON).
- Tests: parse-time content-type handling (PNG/JSON/text/SVG + lying header),
  detectContentTypeFromBytes / isByteFormatContentType, and the data-only formatter path.
@vasharma05-bruno

Copy link
Copy Markdown
Contributor Author

Hi @arpit-bruno,
Currently we are using Buffer, because it's implemented in the Bruno app in the same manner, but as per your suggestion to use TextDecoder, browser's native API, I'll need to revamp the whole change.

As per our discussion, we can take the work on replacing the Buffer with TextDecoder as a follow up.
Thanks!

…he sticky-preview e2e

The response tab bar keeps only the active tab visible and overflows the rest into a
menu; which tabs overflow depends on viewport/font metrics, so the tab-switch re-render
was flaky in CI (clicking the now-overflowed Response tab timed out on a not-visible
element). Re-fetch the identical image response instead — a stable, always-visible
trigger that exercises the same guard (sticky-preview survives an unchanged content type).
…e pdf.js worker

react-pdf's <Page> rendered a text layer on top of the canvas, but the required
TextLayer CSS was never imported ("TextLayer styles not found"), so the unstyled
text layer painted a second, visible copy of each page's content — the page appeared
rendered twice. The preview is read-only, so disable the text (and keep the annotation)
layer: only the canvas renders now.

Also set pdfjs.GlobalWorkerOptions.workerSrc to the bundled worker — without it react-pdf
fell back to a fake worker that failed to resolve in a Vite build, so PDFs didn't render
at all. Verified: pages render once, unit suite green, and the production build emits the
worker asset.
arpit-bruno
arpit-bruno previously approved these changes Jul 29, 2026

@arpit-bruno arpit-bruno left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

arpit-bruno
arpit-bruno previously approved these changes Jul 29, 2026
@vasharma05-bruno vasharma05-bruno changed the title feat(playground): response body formatting, preview, and format selector feat(playground): response body formatting, preview, and format selector (BRU-3764) Jul 29, 2026
@arpit-bruno
arpit-bruno merged commit 89da487 into usebruno:main Jul 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants