mgply09ox: Publish an image post through a server upload pipeline

This commit is contained in:
2026-10-19 14:46:13 -06:00
parent fe38682124
commit b4fb345f90
9 changed files with 581 additions and 31 deletions
+21 -5
View File
@@ -79,7 +79,7 @@ describe("publishAndConfirm", () => {
it("returns the reloaded page only when the id is on the first page", async () => {
const state = { id: null as string | null };
const page = { items: [item("p9"), item("p1")], nextCursor: null };
const got = await publishAndConfirm("hi", state, { send: async () => "p9", fetchPage: async () => page });
const got = await publishAndConfirm("hi", null, state, { send: async () => "p9", fetchPage: async () => page });
expect(got).toBe(page);
expect(state.id).toBeNull();
});
@@ -88,17 +88,17 @@ describe("publishAndConfirm", () => {
const state = { id: null as string | null };
const send = vi.fn(async () => "p9");
const miss = async () => ({ items: [item("p1")], nextCursor: null });
await expect(publishAndConfirm("hi", state, { send, fetchPage: miss })).rejects.toBeInstanceOf(PostError);
await expect(publishAndConfirm("hi", null, state, { send, fetchPage: miss })).rejects.toBeInstanceOf(PostError);
expect(state.id).toBe("p9");
const hit = async () => ({ items: [item("p9")], nextCursor: null });
await publishAndConfirm("hi", state, { send, fetchPage: hit });
await publishAndConfirm("hi", null, state, { send, fetchPage: hit });
expect(send).toHaveBeenCalledTimes(1);
});
it("sendPost maps 401 to signed out and other failures to publish_failed", async () => {
const f = (status: number) => (async () => new Response("{}", { status })) as unknown as typeof fetch;
await expect(sendPost("x", f(401))).rejects.toMatchObject({ signedOut: true });
await expect(sendPost("x", f(500))).rejects.toMatchObject({ signedOut: false });
await expect(sendPost("x", null, f(401))).rejects.toMatchObject({ signedOut: true });
await expect(sendPost("x", null, f(500))).rejects.toMatchObject({ signedOut: false });
});
});
@@ -124,4 +124,20 @@ describe("Composer", () => {
expect(html).toContain("No posts yet.");
expect(html).toContain("composer-text");
});
it("shows an image picker and enables Post with a file but no text", () => {
const f = new File(["x"], "photo.jpg", { type: "image/jpeg" });
const html = renderToStaticMarkup(createElement(Composer, { ...base, file: f, onFile: () => {} }));
expect(html).toContain("Add image");
expect(html).toContain("photo.jpg");
expect(html).not.toMatch(/<button[^>]*class="composer-post"[^>]*disabled/);
});
it("keeps the text and the image name on a publish failure", () => {
const f = new File(["x"], "sunset.png", { type: "image/png" });
const html = renderToStaticMarkup(
createElement(Composer, { ...base, value: "my draft", file: f, error: true, onFile: () => {} }),
);
expect(html).toContain("Publishing the post failed");
expect(html).toContain("my draft");
expect(html).toContain("sunset.png");
});
});