1import { parseNewThreadLink } from "@t3tools/shared/promptLinks";
2import { describe, expect, it } from "vite-plus/test";
3
4import {
5 latestThreadEnvironmentIds,
6 linkedThreadDraftAction,
7 promptLinkNotice,
8 promptLinkScratchEnvironmentId,
9 promptLinkSearchFromParams,
10} from "./prompt-link-model";
11
12describe("promptLinkSearchFromParams", () => {
13 it("round-trips decoded route params into the shared parser", () => {
14 const search = promptLinkSearchFromParams({
15 prompt: "Fix the bug & add tests = done?",
16 repo: ["pingdotgg/t3code", "ignored/second"],
17 provider: "codex",
18 screen: "NewTask",
19 });
20
21 expect(parseNewThreadLink(search ?? "")).toEqual({
22 ok: true,
23 value: {
24 kind: "new",
25 prompt: { text: "Fix the bug & add tests = done?", hiddenCharacters: 0 },
26 repository: { owner: "pingdotgg", name: "t3code" },
27 provider: "codex",
28 model: null,
29 },
30 });
31 });
32
33 it("is null for routes without a prompt link", () => {
34 expect(promptLinkSearchFromParams({ incomingShareId: "share-1" })).toBeNull();
35 expect(promptLinkSearchFromParams(undefined)).toBeNull();
36 });
37});
38
39describe("promptLinkNotice", () => {
40 it("replaces the plain notice with the hidden character warning", () => {
41 expect(promptLinkNotice({ hiddenCharacters: 0 })).toBe(
42 "This prompt came from a link. Read it before you send.",
43 );
44 expect(promptLinkNotice({ hiddenCharacters: 2, modelUnavailable: true })).toBe(
45 "This prompt had hidden characters, it may be malicious. They were removed. Read it before you send.\n\nThe requested model is not available, so your default is used.",
46 );
47 });
48});
49
50describe("linkedThreadDraftAction", () => {
51 it("fills an empty composer and asks before replacing typed text", () => {
52 expect(linkedThreadDraftAction(" \n", "Do it")).toBe("fill");
53 expect(linkedThreadDraftAction("Do it", "Do it")).toBe("keep");
54 expect(linkedThreadDraftAction("My notes", "Do it")).toBe("ask");
55 });
56});
57
58describe("promptLinkScratchEnvironmentId", () => {
59 it("prefers the most recently active machine that offers threads without a project", () => {
60 expect(promptLinkScratchEnvironmentId(["a", "b", "c"], ["c", "b"])).toBe("b");
61 expect(promptLinkScratchEnvironmentId(["a"], ["c"])).toBe("c");
62 expect(promptLinkScratchEnvironmentId(["a"], [])).toBeNull();
63 });
64});
65
66describe("latestThreadEnvironmentIds", () => {
67 it("orders machines by their latest thread", () => {
68 expect(
69 latestThreadEnvironmentIds([
70 { environmentId: "a", updatedAt: "2026-01-02T00:00:00.000Z" },
71 { environmentId: "b", updatedAt: "2026-01-03T00:00:00.000Z" },
72 { environmentId: "a", updatedAt: "2026-01-04T00:00:00.000Z" },
73 ]),
74 ).toEqual(["a", "b"]);
75 });
76});