Files
fusion/packages/dashboard/app/components/__tests__/MailboxNativeStructureEmbeds.test.tsx
gsxdsm cf3f5e9bf0 FN-8292: embed native structures in mail messages
Embed selected native project structures directly in mailbox messages and drafts.

- Persist native structure embeds in message metadata and expose their shared types.
- Add composer selection, mailbox rendering, previews, and dashboard navigation for linked structures.
- Cover metadata persistence and mailbox embed behavior with core and dashboard tests.

Files changed:
 .changeset/fn-8292-mail-native-structure-embeds.md |  7 ++
 docs/dashboard-guide.md                            |  1 +
 .../message-metadata-native-structures.test.ts     | 25 +++++++
 .../__tests__/postgres/message-store.pg.test.ts    | 21 ++++++
 packages/core/src/index.ts                         |  2 +-
 packages/core/src/types.ts                         | 32 +++++++++
 packages/core/src/types/messages.ts                | 14 ++++
 packages/dashboard/app/components/MailboxModal.css | 29 ++++++++
 packages/dashboard/app/components/MailboxModal.tsx | 13 +++-
 .../components/MailboxNativeStructureEmbeds.tsx    | 37 ++++++++++
 packages/dashboard/app/components/MailboxView.tsx  | 14 +++-
 .../dashboard/app/components/MessageComposer.tsx   | 65 ++++++++++++++++--
 .../app/components/NativeStructurePreview.tsx      |  6 +-
 .../__tests__/MailboxModal.cache.test.tsx          |  8 +--
 .../app/components/__tests__/MailboxModal.test.tsx |  9 +++
 .../MailboxNativeStructureEmbeds.test.tsx          | 42 ++++++++++++
 .../app/components/__tests__/MailboxView.test.tsx  |  9 +++
 .../components/__tests__/MessageComposer.test.tsx  | 25 +++++++
 .../app/components/dashboard/MainContent.tsx       | 78 +++++++++++++++++++++-
 .../MainContent.mailbox-view-task.test.tsx         | 46 ++++++++++++-
 20 files changed, 459 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-8292

Fusion-Task-Lineage: ae6cfb9c-a764-407c-bd45-cfd879ccdd3e

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-18 19:45:08 -07:00

43 lines
2.2 KiB
TypeScript

import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { Message, NativeStructureEmbed } from "@fusion/core";
import { fetchNativeStructurePreview } from "../../api";
import { MailboxNativeStructureEmbeds } from "../MailboxNativeStructureEmbeds";
vi.mock("../../api", () => ({ fetchNativeStructurePreview: vi.fn() }));
const fetchPreview = vi.mocked(fetchNativeStructurePreview);
function message(nativeStructures?: NativeStructureEmbed[]): Pick<Message, "metadata"> {
return { metadata: nativeStructures ? { nativeStructures } : undefined };
}
describe("MailboxNativeStructureEmbeds", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("does not create an attachment shell without embeds", () => {
const { container } = render(<MailboxNativeStructureEmbeds message={message()} onOpen={vi.fn()} />);
expect(container).toBeEmptyDOMElement();
});
it("renders every persisted embed and forwards preview navigation", async () => {
const onOpen = vi.fn();
fetchPreview.mockResolvedValue({ available: true, kind: "mission", kindLabel: "Mission", title: "Launch mail", excerpt: "Review", openTarget: { view: "missions", id: "M-1" } });
render(<MailboxNativeStructureEmbeds message={message([
{ kind: "mission", id: "M-1", label: "Launch mail" },
{ kind: "goal", id: "G-1", label: "Ship" },
])} onOpen={onOpen} />);
await waitFor(() => expect(screen.getAllByTestId("native-structure-preview")).toHaveLength(2));
fireEvent.click(screen.getAllByRole("button", { name: /Open Mission/ })[0]);
expect(onOpen).toHaveBeenCalledWith({ kind: "mission", id: "M-1", projectId: undefined }, expect.objectContaining({ available: true }));
});
it("uses the captured label for unavailable targets", async () => {
fetchPreview.mockResolvedValue({ available: false, kind: "mission", id: "M-1", reason: "soft-deleted" });
render(<MailboxNativeStructureEmbeds message={message([{ kind: "mission", id: "M-1", label: "Launch mail" }])} onOpen={vi.fn()} />);
await waitFor(() => expect(screen.getByTestId("native-structure-preview-unavailable")).toHaveTextContent("Launch mail"));
});
});