
























@@ -509,10 +509,161 @@ describe("renderWorkboard", () => {
509509expect(
510510container.querySelector<HTMLButtonElement>(".workboard-toolbar__actions .btn.primary"),
511511).toBeNull();
512+expect(container.querySelector<HTMLSelectElement>(".workboard-card__move-select")).toBeNull();
512513expect(container.querySelector(".workboard-card")?.getAttribute("draggable")).toBe("false");
513514expect(container.querySelector(".workboard-card")?.getAttribute("role")).toBe("button");
514515});
515516517+it("moves a card from the compact status control", async () => {
518+const host = {};
519+const state = getWorkboardState(host);
520+state.loaded = true;
521+state.cards = [
522+{
523+id: "card-1",
524+title: "Keyboard move",
525+status: "todo",
526+priority: "normal",
527+labels: [],
528+position: 1000,
529+createdAt: 1,
530+updatedAt: 1,
531+},
532+];
533+const request = vi.fn(async () => ({
534+card: { ...state.cards[0], status: "blocked", position: 1000, updatedAt: 2 },
535+}));
536+const props = {
537+ host,
538+client: { request } as unknown as GatewayBrowserClient,
539+connected: true,
540+pluginEnabled: true,
541+agentsList: null,
542+sessions: [],
543+onOpenSession: () => undefined,
544+onRequestUpdate: () => undefined,
545+};
546+const container = document.createElement("div");
547+548+render(renderWorkboard(props), container);
549+const moveSelect = container.querySelector<HTMLSelectElement>(".workboard-card__move-select");
550+expect(moveSelect?.value).toBe("todo");
551+expect(moveSelect?.tagName).toBe("SELECT");
552+expect(moveSelect?.getAttribute("aria-keyshortcuts")).toBe("ArrowLeft ArrowRight");
553+expect(moveSelect?.getAttribute("aria-label")).toBe("Status: Keyboard move");
554+555+moveSelect!.value = "blocked";
556+moveSelect!.dispatchEvent(new Event("change", { bubbles: true }));
557+await Promise.resolve();
558+await Promise.resolve();
559+render(renderWorkboard(props), container);
560+561+expect(request).toHaveBeenCalledWith("workboard.cards.move", {
562+id: "card-1",
563+status: "blocked",
564+position: 1000,
565+});
566+const blockedColumn = [...container.querySelectorAll<HTMLElement>(".workboard-column")].find(
567+(column) => column.querySelector("h2")?.textContent === "Blocked",
568+);
569+expect(blockedColumn?.textContent).toContain("Keyboard move");
570+expect(state.cards[0]).toMatchObject({ status: "blocked", updatedAt: 2 });
571+});
572+573+it("moves a focused status control with keyboard arrows", async () => {
574+const host = {};
575+const state = getWorkboardState(host);
576+state.loaded = true;
577+state.cards = [
578+{
579+id: "card-1",
580+title: "Keyboard arrow move",
581+status: "todo",
582+priority: "normal",
583+labels: [],
584+position: 1000,
585+createdAt: 1,
586+updatedAt: 1,
587+},
588+];
589+const request = vi.fn(async () => ({
590+card: { ...state.cards[0], status: "scheduled", position: 1000, updatedAt: 2 },
591+}));
592+const props = {
593+ host,
594+client: { request } as unknown as GatewayBrowserClient,
595+connected: true,
596+pluginEnabled: true,
597+agentsList: null,
598+sessions: [],
599+onOpenSession: () => undefined,
600+onRequestUpdate: () => undefined,
601+};
602+const container = document.createElement("div");
603+604+render(renderWorkboard(props), container);
605+const moveSelect = container.querySelector<HTMLSelectElement>(".workboard-card__move-select");
606+const dispatched = moveSelect!.dispatchEvent(
607+new KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true, cancelable: true }),
608+);
609+await Promise.resolve();
610+await Promise.resolve();
611+612+expect(dispatched).toBe(false);
613+expect(request).toHaveBeenCalledWith("workboard.cards.move", {
614+id: "card-1",
615+status: "scheduled",
616+position: 1000,
617+});
618+expect(state.cards[0]).toMatchObject({ status: "scheduled", updatedAt: 2 });
619+});
620+621+it("does not queue status-control moves while a card is busy", async () => {
622+const host = {};
623+const state = getWorkboardState(host);
624+state.loaded = true;
625+state.busyCardId = "card-1";
626+state.cards = [
627+{
628+id: "card-1",
629+title: "Busy move",
630+status: "todo",
631+priority: "normal",
632+labels: [],
633+position: 1000,
634+createdAt: 1,
635+updatedAt: 1,
636+},
637+];
638+const request = vi.fn();
639+const props = {
640+ host,
641+client: { request } as unknown as GatewayBrowserClient,
642+connected: true,
643+pluginEnabled: true,
644+agentsList: null,
645+sessions: [],
646+onOpenSession: () => undefined,
647+onRequestUpdate: () => undefined,
648+};
649+const container = document.createElement("div");
650+651+render(renderWorkboard(props), container);
652+const moveSelect = container.querySelector<HTMLSelectElement>(".workboard-card__move-select");
653+expect(moveSelect?.disabled).toBe(true);
654+655+moveSelect!.value = "blocked";
656+moveSelect!.dispatchEvent(new Event("change", { bubbles: true }));
657+const dispatched = moveSelect!.dispatchEvent(
658+new KeyboardEvent("keydown", { key: "ArrowRight", bubbles: true, cancelable: true }),
659+);
660+await Promise.resolve();
661+662+expect(dispatched).toBe(false);
663+expect(request).not.toHaveBeenCalled();
664+expect(state.cards[0]).toMatchObject({ status: "todo", updatedAt: 1 });
665+});
666+516667it("offers start controls when a linked session no longer exists", () => {
517668const host = {};
518669const state = getWorkboardState(host);
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。