Files
GearBox/tests/services/storage.service.test.ts
Jean-Luc Makiola be1197f3da
Some checks failed
CI / ci (push) Successful in 1m7s
CI / e2e (push) Has been skipped
CI / deploy (push) Failing after 11s
fix: lint formatting in storage test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 15:31:39 +02:00

163 lines
4.8 KiB
TypeScript

import { beforeEach, describe, expect, mock, test } from "bun:test";
// Mock the S3 client send method
const mockSend = mock(() => Promise.resolve({}));
const mockGetSignedUrl = mock(() =>
Promise.resolve("https://s3.example.com/gearbox-images/test.jpg?signed=1"),
);
// Mock modules before importing the service
mock.module("@aws-sdk/client-s3", () => ({
S3Client: class MockS3Client {
send = mockSend;
},
PutObjectCommand: class MockPutObjectCommand {
input: Record<string, unknown>;
constructor(input: Record<string, unknown>) {
this.input = input;
}
},
DeleteObjectCommand: class MockDeleteObjectCommand {
input: Record<string, unknown>;
constructor(input: Record<string, unknown>) {
this.input = input;
}
},
GetObjectCommand: class MockGetObjectCommand {
input: Record<string, unknown>;
constructor(input: Record<string, unknown>) {
this.input = input;
}
},
}));
mock.module("@aws-sdk/s3-request-presigner", () => ({
getSignedUrl: mockGetSignedUrl,
}));
// Set env vars before importing the service
process.env.S3_ENDPOINT = "http://localhost:3900";
process.env.S3_ACCESS_KEY = "test-access-key";
process.env.S3_SECRET_KEY = "test-secret-key";
process.env.S3_BUCKET = "gearbox-images";
process.env.S3_REGION = "garage";
// Import after mocking
const { uploadImage, deleteImage, getImageUrl, withImageUrl, withImageUrls } =
await import("@/server/services/storage.service");
describe("storage.service", () => {
beforeEach(() => {
mockSend.mockClear();
mockGetSignedUrl.mockClear();
mockGetSignedUrl.mockResolvedValue(
"https://s3.example.com/gearbox-images/test.jpg?signed=1",
);
});
describe("uploadImage", () => {
test("calls PutObjectCommand with correct params", async () => {
const buffer = Buffer.from("fake-image-data");
await uploadImage(buffer, "test-image.jpg", "image/jpeg");
expect(mockSend).toHaveBeenCalledTimes(1);
const command = mockSend.mock.calls[0][0] as {
input: Record<string, unknown>;
};
expect(command.input.Bucket).toBe("gearbox-images");
expect(command.input.Key).toBe("test-image.jpg");
expect(command.input.ContentType).toBe("image/jpeg");
expect(Buffer.isBuffer(command.input.Body)).toBe(true);
});
test("handles ArrayBuffer input", async () => {
const arrayBuffer = new ArrayBuffer(10);
await uploadImage(arrayBuffer, "test.png", "image/png");
expect(mockSend).toHaveBeenCalledTimes(1);
const command = mockSend.mock.calls[0][0] as {
input: Record<string, unknown>;
};
expect(Buffer.isBuffer(command.input.Body)).toBe(true);
});
});
describe("deleteImage", () => {
test("calls DeleteObjectCommand with correct params", async () => {
await deleteImage("test-image.jpg");
expect(mockSend).toHaveBeenCalledTimes(1);
const command = mockSend.mock.calls[0][0] as {
input: Record<string, unknown>;
};
expect(command.input.Bucket).toBe("gearbox-images");
expect(command.input.Key).toBe("test-image.jpg");
});
});
describe("getImageUrl", () => {
test("calls getSignedUrl and returns result", async () => {
const url = await getImageUrl("test-image.jpg");
expect(mockGetSignedUrl).toHaveBeenCalledTimes(1);
expect(url).toBe(
"https://s3.example.com/gearbox-images/test.jpg?signed=1",
);
});
});
describe("withImageUrl", () => {
test("returns null imageUrl when imageFilename is null", async () => {
const record = { id: 1, name: "Test Item", imageFilename: null };
const result = await withImageUrl(record);
expect(result.imageUrl).toBeNull();
expect(result.id).toBe(1);
expect(result.name).toBe("Test Item");
expect(mockGetSignedUrl).not.toHaveBeenCalled();
});
test("returns presigned URL when imageFilename is present", async () => {
const record = {
id: 1,
name: "Test Item",
imageFilename: "photo.jpg",
};
const result = await withImageUrl(record);
expect(result.imageUrl).toBe(
"https://s3.example.com/gearbox-images/test.jpg?signed=1",
);
expect(result.id).toBe(1);
expect(mockGetSignedUrl).toHaveBeenCalledTimes(1);
});
});
describe("withImageUrls", () => {
test("processes array of records correctly", async () => {
const records = [
{ id: 1, imageFilename: "a.jpg" },
{ id: 2, imageFilename: null },
{ id: 3, imageFilename: "b.png" },
];
const results = await withImageUrls(records);
expect(results).toHaveLength(3);
expect(results[0].imageUrl).toBe(
"https://s3.example.com/gearbox-images/test.jpg?signed=1",
);
expect(results[1].imageUrl).toBeNull();
expect(results[2].imageUrl).toBe(
"https://s3.example.com/gearbox-images/test.jpg?signed=1",
);
// Called twice: for records[0] and records[2]
expect(mockGetSignedUrl).toHaveBeenCalledTimes(2);
});
test("handles empty array", async () => {
const results = await withImageUrls([]);
expect(results).toHaveLength(0);
});
});
});