grocery-app/backend/tests/available-item.model.test.js

160 lines
4.6 KiB
JavaScript

jest.mock("../db/pool", () => ({
query: jest.fn(),
}));
const pool = require("../db/pool");
const AvailableItems = require("../models/available-item.model");
describe("available-item.model", () => {
beforeEach(() => {
pool.query.mockReset();
});
test("lists manageable items from household/store history even without stored overrides", async () => {
pool.query.mockResolvedValueOnce({
rowCount: 1,
rows: [
{
item_id: 55,
item_name: "milk",
item_image: null,
image_mime_type: null,
item_type: null,
item_group: null,
zone: null,
has_managed_settings: false,
},
],
});
const result = await AvailableItems.listAvailableItems(1, 2);
expect(result).toEqual([
expect.objectContaining({
item_id: 55,
item_name: "milk",
has_managed_settings: false,
}),
]);
expect(pool.query).toHaveBeenCalledWith(
expect.stringContaining("WITH manageable_items AS"),
[1, 2]
);
});
test("creates an available item using an existing catalog item", async () => {
pool.query
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55, name: "milk" }] })
.mockResolvedValueOnce({ rowCount: 1, rows: [] })
.mockResolvedValueOnce({
rowCount: 1,
rows: [
{
item_id: 55,
item_name: "milk",
item_image: null,
image_mime_type: null,
item_type: "dairy",
item_group: "Milk",
zone: "Dairy & Refrigerated",
},
],
});
const result = await AvailableItems.createAvailableItem(1, 2, "Milk");
expect(result).toEqual(
expect.objectContaining({
item_id: 55,
item_name: "milk",
})
);
expect(pool.query).toHaveBeenNthCalledWith(
1,
"SELECT id, name FROM items WHERE name ILIKE $1",
["milk"]
);
expect(pool.query).toHaveBeenNthCalledWith(
2,
expect.stringContaining("INSERT INTO household_store_available_items"),
[1, 2, 55, null, null]
);
});
test("creates an available item and inserts a new master item when needed", async () => {
pool.query
.mockResolvedValueOnce({ rowCount: 0, rows: [] })
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 77, name: "granola" }] })
.mockResolvedValueOnce({ rowCount: 1, rows: [] })
.mockResolvedValueOnce({
rowCount: 1,
rows: [{ item_id: 77, item_name: "granola" }],
});
const result = await AvailableItems.createAvailableItem(1, 2, "Granola");
expect(result).toEqual(expect.objectContaining({ item_id: 77, item_name: "granola" }));
expect(pool.query).toHaveBeenNthCalledWith(
2,
"INSERT INTO items (name) VALUES ($1) RETURNING id, name",
["granola"]
);
});
test("updates available item images and returns refreshed data", async () => {
const imageBuffer = Buffer.from("abc");
pool.query
.mockResolvedValueOnce({ rowCount: 1, rows: [{ item_id: 55 }] })
.mockResolvedValueOnce({ rowCount: 1, rows: [{ item_id: 55 }] })
.mockResolvedValueOnce({
rowCount: 1,
rows: [{
item_id: 55,
item_name: "milk",
item_image: "YWJj",
image_mime_type: "image/jpeg",
has_managed_settings: true,
}],
});
const result = await AvailableItems.updateAvailableItem(1, 2, 55, {
imageBuffer,
mimeType: "image/jpeg",
});
expect(result).toEqual(expect.objectContaining({ item_id: 55, image_mime_type: "image/jpeg" }));
expect(pool.query).toHaveBeenNthCalledWith(
2,
expect.stringContaining("UPDATE household_store_available_items"),
[1, 2, 55, imageBuffer, "image/jpeg"]
);
});
test("imports current household list items idempotently", async () => {
pool.query.mockResolvedValueOnce({
rowCount: 2,
rows: [{ item_id: 10 }, { item_id: 11 }],
});
const result = await AvailableItems.importCurrentListItems(1, 2);
expect(result).toBe(2);
expect(pool.query).toHaveBeenCalledWith(
expect.stringContaining("INSERT INTO household_store_available_items"),
[1, 2]
);
});
test("deletes only the catalog entry", async () => {
pool.query.mockResolvedValueOnce({ rowCount: 1, rows: [] });
const deleted = await AvailableItems.deleteAvailableItem(1, 2, 55);
expect(deleted).toBe(true);
expect(pool.query).toHaveBeenCalledWith(
expect.stringContaining("DELETE FROM household_store_available_items"),
[1, 2, 55]
);
});
});