218 lines · 6.3 KB · TypeScript
RawDownload
import { createElement } from "react";import { renderToStaticMarkup } from "react-dom/server";import { afterEach, describe, expect, it, vi } from "vite-plus/test"; const stageArtworkState = vi.hoisted(() => ({  mode: "none" as "artwork" | "none",  variant: null as "nightly" | "dev" | null,})); vi.mock("~/hooks/useSettings", () => ({  useEnvironmentIdentificationMode: () => stageArtworkState.mode,}));vi.mock("../SidebarStageBackdrop", () => ({  StageBackdropButtonArt: ({ variant }: { variant: string }) => `stage-${variant}`,  useSidebarStageBackdropVariant: (enabled = true) => (enabled ? stageArtworkState.variant : null),})); import { ComposerPrimaryActions, formatPendingPrimaryActionLabel } from "./ComposerPrimaryActions"; function renderPendingActions(isRunning: boolean) {  return renderToStaticMarkup(    createElement(ComposerPrimaryActions, {      compact: true,      pendingAction: {        questionIndex: 0,        isLastQuestion: true,        canAdvance: true,        isResponding: false,        isComplete: true,      },      isRunning,      showPlanFollowUpPrompt: false,      promptHasText: false,      isSendBusy: false,      sendDisabledReason: null,      isConnecting: false,      isEnvironmentUnavailable: false,      isPreparingWorktree: false,      hasSendableContent: false,      onPreviousPendingQuestion: () => {},      onInterrupt: () => {},      onImplementPlanInNewThread: () => {},    }),  );} function renderStandaloneStop() {  return renderToStaticMarkup(    createElement(ComposerPrimaryActions, {      compact: true,      pendingAction: null,      isRunning: true,      showPlanFollowUpPrompt: false,      promptHasText: false,      isSendBusy: false,      sendDisabledReason: null,      isConnecting: false,      isEnvironmentUnavailable: false,      isPreparingWorktree: false,      hasSendableContent: false,      onPreviousPendingQuestion: () => {},      onInterrupt: () => {},      onImplementPlanInNewThread: () => {},    }),  );} function renderSendButton() {  return renderToStaticMarkup(    createElement(ComposerPrimaryActions, {      compact: true,      pendingAction: null,      isRunning: false,      showPlanFollowUpPrompt: false,      promptHasText: true,      isSendBusy: false,      sendDisabledReason: null,      isConnecting: false,      isEnvironmentUnavailable: false,      isPreparingWorktree: false,      hasSendableContent: true,      onPreviousPendingQuestion: () => {},      onInterrupt: () => {},      onImplementPlanInNewThread: () => {},    }),  );} afterEach(() => {  stageArtworkState.mode = "none";  stageArtworkState.variant = null;}); describe("formatPendingPrimaryActionLabel", () => {  it("returns 'Submitting...' while responding", () => {    expect(      formatPendingPrimaryActionLabel({        compact: false,        isLastQuestion: false,        isResponding: true,        questionIndex: 0,      }),    ).toBe("Submitting...");  });   it("returns 'Submitting...' while responding regardless of other flags", () => {    expect(      formatPendingPrimaryActionLabel({        compact: true,        isLastQuestion: true,        isResponding: true,        questionIndex: 3,      }),    ).toBe("Submitting...");  });   it("returns 'Submit' in compact mode on the last question", () => {    expect(      formatPendingPrimaryActionLabel({        compact: true,        isLastQuestion: true,        isResponding: false,        questionIndex: 0,      }),    ).toBe("Submit");  });   it("returns 'Next' in compact mode when not the last question", () => {    expect(      formatPendingPrimaryActionLabel({        compact: true,        isLastQuestion: false,        isResponding: false,        questionIndex: 1,      }),    ).toBe("Next");  });   it("returns 'Next question' when not the last question", () => {    expect(      formatPendingPrimaryActionLabel({        compact: false,        isLastQuestion: false,        isResponding: false,        questionIndex: 0,      }),    ).toBe("Next question");  });   it("returns singular 'Submit answer' on the last question when it is the only question", () => {    expect(      formatPendingPrimaryActionLabel({        compact: false,        isLastQuestion: true,        isResponding: false,        questionIndex: 0,      }),    ).toBe("Submit answer");  });   it("returns plural 'Submit answers' on the last question when there are multiple questions", () => {    expect(      formatPendingPrimaryActionLabel({        compact: false,        isLastQuestion: true,        isResponding: false,        questionIndex: 1,      }),    ).toBe("Submit answers");  });   it("returns plural 'Submit answers' for higher question indices", () => {    expect(      formatPendingPrimaryActionLabel({        compact: false,        isLastQuestion: true,        isResponding: false,        questionIndex: 5,      }),    ).toBe("Submit answers");  });}); describe("ComposerPrimaryActions", () => {  it("offers Stop generation while a running turn is waiting for user input", () => {    expect(renderPendingActions(true)).toContain('aria-label="Stop generation"');  });   it("does not offer Stop generation for a pending request without a running turn", () => {    expect(renderPendingActions(false)).not.toContain('aria-label="Stop generation"');  });   it("matches the small pending action size without changing the standalone size", () => {    expect(renderPendingActions(true)).toContain("size-8 sm:size-7");    expect(renderStandaloneStop()).toContain("size-8 sm:h-8 sm:w-8");    expect(renderStandaloneStop()).not.toContain("sm:size-7");  });   it("renders stage artwork inside the send button when artwork identification is active", () => {    stageArtworkState.mode = "artwork";    stageArtworkState.variant = "nightly";     const markup = renderSendButton();     expect(markup).toContain("stage-nightly");    expect(markup).toContain("bg-transparent text-white");    expect(markup).not.toContain("bg-message-action text-message-action-foreground");  });   it("keeps the normal send-button fill when artwork identification is inactive", () => {    stageArtworkState.variant = "nightly";     const markup = renderSendButton();     expect(markup).not.toContain("stage-nightly");    expect(markup).toContain("bg-message-action text-message-action-foreground");  });});