The live screen opens wide beside the chat while the bot works on it or asks for a takeover, a file the bot presents as its result opens next to the conversation, and a question that scrolled away gets a "Needs you" pill back to it. Shared core rules derive the focus from signals clients already have (pointer events, takeover requests, a new `present` flag on attach_file, pending asks), move the pane only on focus edges, never replace a pane the user opened, and learn per bot whether the screen opens on its own. Pane widths persist per device; mobile shows a pill that opens the computer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7VSRHHzyt2KwoCkUkZ2Gc
32 lines
956 B
TypeScript
32 lines
956 B
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { parseCsvPreview } from "./csv-preview";
|
|
|
|
describe("parseCsvPreview", () => {
|
|
it("reads quoted fields, doubled quotes and CRLF rows", () => {
|
|
expect(parseCsvPreview('name,note\r\n"Smith, Ann","said ""hi"""\r\nBo,\n')).toEqual({
|
|
rows: [
|
|
["name", "note"],
|
|
["Smith, Ann", 'said "hi"'],
|
|
["Bo", ""],
|
|
],
|
|
truncated: false,
|
|
});
|
|
});
|
|
|
|
it("keeps a final row without a trailing newline and skips blank lines", () => {
|
|
expect(parseCsvPreview("a,b\n\n1,2").rows).toEqual([
|
|
["a", "b"],
|
|
["1", "2"],
|
|
]);
|
|
});
|
|
|
|
it("keeps newlines inside quoted fields", () => {
|
|
expect(parseCsvPreview('a\n"line 1\nline 2"').rows).toEqual([["a"], ["line 1\nline 2"]]);
|
|
});
|
|
|
|
it("stops after the row limit", () => {
|
|
const result = parseCsvPreview("1\n2\n3\n4\n", 2);
|
|
expect(result).toEqual({ rows: [["1"], ["2"]], truncated: true });
|
|
});
|
|
});
|