test: share bluebubbles attachment fixtures

This commit is contained in:
Peter Steinberger 2026-03-13 21:23:29 +00:00
parent 89e0e80db3
commit eca22c0cc7
1 changed files with 24 additions and 36 deletions

View File

@ -82,6 +82,15 @@ describe("downloadBlueBubblesAttachment", () => {
).rejects.toThrow("too large"); ).rejects.toThrow("too large");
} }
function mockSuccessfulAttachmentDownload(buffer = new Uint8Array([1])) {
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(buffer.buffer),
});
return buffer;
}
it("throws when guid is missing", async () => { it("throws when guid is missing", async () => {
const attachment: BlueBubblesAttachment = {}; const attachment: BlueBubblesAttachment = {};
await expect( await expect(
@ -159,12 +168,7 @@ describe("downloadBlueBubblesAttachment", () => {
}); });
it("encodes guid in URL", async () => { it("encodes guid in URL", async () => {
const mockBuffer = new Uint8Array([1]); mockSuccessfulAttachmentDownload();
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(mockBuffer.buffer),
});
const attachment: BlueBubblesAttachment = { guid: "att/with/special chars" }; const attachment: BlueBubblesAttachment = { guid: "att/with/special chars" };
await downloadBlueBubblesAttachment(attachment, { await downloadBlueBubblesAttachment(attachment, {
@ -244,12 +248,7 @@ describe("downloadBlueBubblesAttachment", () => {
}); });
it("resolves credentials from config when opts not provided", async () => { it("resolves credentials from config when opts not provided", async () => {
const mockBuffer = new Uint8Array([1]); mockSuccessfulAttachmentDownload();
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(mockBuffer.buffer),
});
const attachment: BlueBubblesAttachment = { guid: "att-config" }; const attachment: BlueBubblesAttachment = { guid: "att-config" };
const result = await downloadBlueBubblesAttachment(attachment, { const result = await downloadBlueBubblesAttachment(attachment, {
@ -270,12 +269,7 @@ describe("downloadBlueBubblesAttachment", () => {
}); });
it("passes ssrfPolicy with allowPrivateNetwork when config enables it", async () => { it("passes ssrfPolicy with allowPrivateNetwork when config enables it", async () => {
const mockBuffer = new Uint8Array([1]); mockSuccessfulAttachmentDownload();
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(mockBuffer.buffer),
});
const attachment: BlueBubblesAttachment = { guid: "att-ssrf" }; const attachment: BlueBubblesAttachment = { guid: "att-ssrf" };
await downloadBlueBubblesAttachment(attachment, { await downloadBlueBubblesAttachment(attachment, {
@ -295,12 +289,7 @@ describe("downloadBlueBubblesAttachment", () => {
}); });
it("auto-allowlists serverUrl hostname when allowPrivateNetwork is not set", async () => { it("auto-allowlists serverUrl hostname when allowPrivateNetwork is not set", async () => {
const mockBuffer = new Uint8Array([1]); mockSuccessfulAttachmentDownload();
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(mockBuffer.buffer),
});
const attachment: BlueBubblesAttachment = { guid: "att-no-ssrf" }; const attachment: BlueBubblesAttachment = { guid: "att-no-ssrf" };
await downloadBlueBubblesAttachment(attachment, { await downloadBlueBubblesAttachment(attachment, {
@ -313,12 +302,7 @@ describe("downloadBlueBubblesAttachment", () => {
}); });
it("auto-allowlists private IP serverUrl hostname when allowPrivateNetwork is not set", async () => { it("auto-allowlists private IP serverUrl hostname when allowPrivateNetwork is not set", async () => {
const mockBuffer = new Uint8Array([1]); mockSuccessfulAttachmentDownload();
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers(),
arrayBuffer: () => Promise.resolve(mockBuffer.buffer),
});
const attachment: BlueBubblesAttachment = { guid: "att-private-ip" }; const attachment: BlueBubblesAttachment = { guid: "att-private-ip" };
await downloadBlueBubblesAttachment(attachment, { await downloadBlueBubblesAttachment(attachment, {
@ -352,6 +336,14 @@ describe("sendBlueBubblesAttachment", () => {
return Buffer.from(body).toString("utf8"); return Buffer.from(body).toString("utf8");
} }
function expectVoiceAttachmentBody() {
const body = mockFetch.mock.calls[0][1]?.body as Uint8Array;
const bodyText = decodeBody(body);
expect(bodyText).toContain('name="isAudioMessage"');
expect(bodyText).toContain("true");
return bodyText;
}
it("marks voice memos when asVoice is true and mp3 is provided", async () => { it("marks voice memos when asVoice is true and mp3 is provided", async () => {
mockFetch.mockResolvedValueOnce({ mockFetch.mockResolvedValueOnce({
ok: true, ok: true,
@ -367,10 +359,7 @@ describe("sendBlueBubblesAttachment", () => {
opts: { serverUrl: "http://localhost:1234", password: "test" }, opts: { serverUrl: "http://localhost:1234", password: "test" },
}); });
const body = mockFetch.mock.calls[0][1]?.body as Uint8Array; const bodyText = expectVoiceAttachmentBody();
const bodyText = decodeBody(body);
expect(bodyText).toContain('name="isAudioMessage"');
expect(bodyText).toContain("true");
expect(bodyText).toContain('filename="voice.mp3"'); expect(bodyText).toContain('filename="voice.mp3"');
}); });
@ -389,8 +378,7 @@ describe("sendBlueBubblesAttachment", () => {
opts: { serverUrl: "http://localhost:1234", password: "test" }, opts: { serverUrl: "http://localhost:1234", password: "test" },
}); });
const body = mockFetch.mock.calls[0][1]?.body as Uint8Array; const bodyText = expectVoiceAttachmentBody();
const bodyText = decodeBody(body);
expect(bodyText).toContain('filename="voice.mp3"'); expect(bodyText).toContain('filename="voice.mp3"');
expect(bodyText).toContain('name="voice.mp3"'); expect(bodyText).toContain('name="voice.mp3"');
}); });