mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-11-13 12:13:42 +01:00
The strip, quiet encrypted rows, warning rows for refused handshakes, the encrypted card with named actions, trust at the first Decrypt, the toast with Undo and Reconnect, the pill's Decrypt everything switch, Settings' Decryption section, the Encrypted sidebar row, and two-step setup. Both body tabs read Body with a type badge; Info leads the request half with the timeline folded in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
111 lines
4.5 KiB
TypeScript
111 lines
4.5 KiB
TypeScript
import { describe, expect, test } from "vite-plus/test";
|
|
import {
|
|
defaultTabFor,
|
|
flowShape,
|
|
learnTab,
|
|
REQUEST_TAB_BODY,
|
|
REQUEST_TAB_HEADERS,
|
|
REQUEST_TAB_INFO,
|
|
RESPONSE_TAB_BODY,
|
|
RESPONSE_TAB_COOKIES,
|
|
RESPONSE_TAB_HEADERS,
|
|
RESPONSE_TAB_MESSAGES,
|
|
type TabMemory,
|
|
} from "./defaultTab";
|
|
|
|
type ShapeFlow = Parameters<typeof flowShape>[0];
|
|
|
|
const ok: ShapeFlow = {
|
|
streamKind: null,
|
|
status: 200,
|
|
error: null,
|
|
cancelled: false,
|
|
requestSize: 0,
|
|
responseSize: 120,
|
|
};
|
|
|
|
function memory(): TabMemory & { items: Map<string, string> } {
|
|
const items = new Map<string, string>();
|
|
return {
|
|
items,
|
|
getItem: (k) => items.get(k) ?? null,
|
|
setItem: (k, v) => void items.set(k, v),
|
|
};
|
|
}
|
|
|
|
const RESPONSE_TABS = [RESPONSE_TAB_BODY, RESPONSE_TAB_HEADERS, RESPONSE_TAB_COOKIES];
|
|
|
|
describe("flowShape", () => {
|
|
test("names what the flow has", () => {
|
|
expect(flowShape(ok)).toBe("response_body");
|
|
expect(flowShape({ ...ok, responseSize: 0, requestSize: 20 })).toBe("request_body");
|
|
expect(flowShape({ ...ok, responseSize: 0 })).toBe("neither");
|
|
expect(flowShape({ ...ok, streamKind: "websocket" })).toBe("stream");
|
|
expect(flowShape({ ...ok, status: null, error: "refused" })).toBe("no_response");
|
|
expect(flowShape({ ...ok, status: null, cancelled: true })).toBe("no_response");
|
|
});
|
|
|
|
test("a body cut after the headers still has its response", () => {
|
|
expect(flowShape({ ...ok, error: "reset mid-body" })).toBe("response_body");
|
|
});
|
|
});
|
|
|
|
describe("defaultTabFor", () => {
|
|
test("follows the table", () => {
|
|
const m = memory();
|
|
// A response body, the request's Info, as there is no request body
|
|
expect(defaultTabFor("request", ok, [], m)).toBe(REQUEST_TAB_INFO);
|
|
expect(defaultTabFor("request", { ...ok, requestSize: 9 }, [], m)).toBe(REQUEST_TAB_BODY);
|
|
expect(defaultTabFor("response", ok, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_BODY);
|
|
// A request body, no response body
|
|
const post = { ...ok, requestSize: 30, responseSize: 0 };
|
|
expect(defaultTabFor("request", post, [], m)).toBe(REQUEST_TAB_BODY);
|
|
expect(defaultTabFor("response", post, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_HEADERS);
|
|
// Neither
|
|
const empty = { ...ok, responseSize: 0 };
|
|
expect(defaultTabFor("request", empty, [], m)).toBe(REQUEST_TAB_INFO);
|
|
expect(defaultTabFor("response", empty, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_HEADERS);
|
|
// A stream
|
|
const ws = { ...ok, streamKind: "websocket" as const };
|
|
expect(defaultTabFor("response", ws, [...RESPONSE_TABS, RESPONSE_TAB_MESSAGES], m)).toBe(
|
|
RESPONSE_TAB_MESSAGES,
|
|
);
|
|
// No response at all: its timeline is in the request's Info
|
|
const failed = { ...ok, status: null, error: "refused", responseSize: 0 };
|
|
expect(defaultTabFor("response", failed, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_HEADERS);
|
|
expect(defaultTabFor("request", failed, [], m)).toBe(REQUEST_TAB_INFO);
|
|
expect(defaultTabFor("request", { ...failed, requestSize: 4 }, [], m)).toBe(REQUEST_TAB_BODY);
|
|
});
|
|
|
|
test("a tab chosen by hand becomes the default for the same shape and pane", () => {
|
|
const m = memory();
|
|
learnTab("response", ok, RESPONSE_TAB_COOKIES, m);
|
|
expect(defaultTabFor("response", ok, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_COOKIES);
|
|
// Not for other shapes, nor the other pane
|
|
const post = { ...ok, requestSize: 30, responseSize: 0 };
|
|
expect(defaultTabFor("response", post, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_HEADERS);
|
|
expect(defaultTabFor("request", ok, ["info", "body", "headers"], m)).toBe(REQUEST_TAB_INFO);
|
|
});
|
|
|
|
test("a learned tab the flow doesn't have falls back to the table", () => {
|
|
const m = memory();
|
|
const ws = { ...ok, streamKind: "websocket" as const };
|
|
learnTab("response", ws, RESPONSE_TAB_MESSAGES, m);
|
|
learnTab("response", ok, RESPONSE_TAB_MESSAGES, m);
|
|
expect(defaultTabFor("response", ok, RESPONSE_TABS, m)).toBe(RESPONSE_TAB_BODY);
|
|
});
|
|
|
|
test("the request half opens on Info unless it has a body, and learns like the response", () => {
|
|
const m = memory();
|
|
const tabs = [REQUEST_TAB_INFO, REQUEST_TAB_BODY, REQUEST_TAB_HEADERS];
|
|
expect(defaultTabFor("request", ok, tabs, m)).toBe(REQUEST_TAB_INFO);
|
|
expect(defaultTabFor("request", { ...ok, requestSize: 5 }, tabs, m)).toBe(REQUEST_TAB_BODY);
|
|
learnTab("request", ok, REQUEST_TAB_HEADERS, m);
|
|
expect(defaultTabFor("request", ok, tabs, m)).toBe(REQUEST_TAB_HEADERS);
|
|
});
|
|
|
|
test("works without storage", () => {
|
|
expect(defaultTabFor("response", ok, RESPONSE_TABS, null)).toBe(RESPONSE_TAB_BODY);
|
|
});
|
|
});
|