181 lines
5.1 KiB
JavaScript
181 lines
5.1 KiB
JavaScript
jest.mock("../db/pool", () => ({
|
|
query: jest.fn(),
|
|
}));
|
|
|
|
const pool = require("../db/pool");
|
|
const List = require("../models/list.model.v2");
|
|
|
|
describe("list.model.v2 addOrUpdateItem", () => {
|
|
beforeEach(() => {
|
|
pool.query.mockReset();
|
|
});
|
|
|
|
test("returns household store item metadata when creating a new list item", async () => {
|
|
pool.query
|
|
.mockResolvedValueOnce({ rowCount: 0, rows: [] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55, name: "milk" }] })
|
|
.mockResolvedValueOnce({ rowCount: 0, rows: [] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 88 }] });
|
|
|
|
const result = await List.addOrUpdateItem(1, 2, "Milk", 3, 7);
|
|
|
|
expect(result).toEqual({
|
|
listId: 88,
|
|
itemId: 55,
|
|
householdStoreItemId: 55,
|
|
itemName: "milk",
|
|
quantity: 3,
|
|
previousQuantity: 0,
|
|
historyQuantity: 3,
|
|
wasBought: false,
|
|
isNew: true,
|
|
});
|
|
expect(pool.query).toHaveBeenNthCalledWith(
|
|
1,
|
|
expect.stringContaining("FROM household_store_items"),
|
|
[1, 2, "milk"]
|
|
);
|
|
expect(pool.query).toHaveBeenNthCalledWith(
|
|
2,
|
|
expect.stringContaining("INSERT INTO household_store_items"),
|
|
[1, 2, "milk", "milk"]
|
|
);
|
|
});
|
|
|
|
test("returns household store item metadata when updating an existing list item", async () => {
|
|
pool.query
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55, name: "milk" }] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 88, bought: false, quantity: 2 }] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [] });
|
|
|
|
const result = await List.addOrUpdateItem(1, 2, "Milk", 4, 7);
|
|
|
|
expect(result).toEqual({
|
|
listId: 88,
|
|
itemId: 55,
|
|
householdStoreItemId: 55,
|
|
itemName: "milk",
|
|
quantity: 4,
|
|
previousQuantity: 2,
|
|
historyQuantity: 2,
|
|
wasBought: false,
|
|
isNew: false,
|
|
});
|
|
expect(pool.query).toHaveBeenNthCalledWith(
|
|
3,
|
|
expect.stringContaining("UPDATE household_lists"),
|
|
[4, undefined, 88]
|
|
);
|
|
});
|
|
|
|
test("uses the full requested quantity when reopening a bought list item", async () => {
|
|
pool.query
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55, name: "milk" }] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 88, bought: true, quantity: 2 }] })
|
|
.mockResolvedValueOnce({ rowCount: 1, rows: [] });
|
|
|
|
const result = await List.addOrUpdateItem(1, 2, "Milk", 4, 7);
|
|
|
|
expect(result).toEqual(
|
|
expect.objectContaining({
|
|
listId: 88,
|
|
quantity: 4,
|
|
previousQuantity: 2,
|
|
historyQuantity: 4,
|
|
wasBought: true,
|
|
isNew: false,
|
|
})
|
|
);
|
|
});
|
|
|
|
test("limits added_by_users to history entries that account for current quantity", async () => {
|
|
pool.query.mockResolvedValueOnce({ rowCount: 0, rows: [] });
|
|
|
|
await List.getHouseholdStoreList(1, 2);
|
|
|
|
const sql = pool.query.mock.calls[0][0];
|
|
expect(sql).toContain("ORDER BY hlh.added_on DESC, hlh.id DESC");
|
|
expect(sql).toContain("active_history.newer_quantity < GREATEST(hl.quantity, 0)");
|
|
});
|
|
});
|
|
|
|
describe("list.model.v2 classification helpers", () => {
|
|
beforeEach(() => {
|
|
pool.query.mockReset();
|
|
});
|
|
|
|
test("gets classification using household, location, and household-store item ids", async () => {
|
|
pool.query.mockResolvedValueOnce({
|
|
rowCount: 1,
|
|
rows: [
|
|
{
|
|
item_type: "dairy",
|
|
item_group: "Milk",
|
|
zone: "Dairy & Refrigerated",
|
|
confidence: 1,
|
|
source: "user",
|
|
},
|
|
],
|
|
});
|
|
|
|
const result = await List.getClassification(1, 2, 55);
|
|
|
|
expect(result).toEqual({
|
|
item_type: "dairy",
|
|
item_group: "Milk",
|
|
zone: "Dairy & Refrigerated",
|
|
confidence: 1,
|
|
source: "user",
|
|
});
|
|
expect(pool.query).toHaveBeenCalledWith(
|
|
expect.stringContaining("household_store_item_id = $3"),
|
|
[1, 2, 55]
|
|
);
|
|
});
|
|
|
|
test("upserts classification using household-location item conflict target", async () => {
|
|
pool.query
|
|
.mockResolvedValueOnce({
|
|
rowCount: 1,
|
|
rows: [{ id: 12, name: "Dairy & Refrigerated", sort_order: 60 }],
|
|
})
|
|
.mockResolvedValueOnce({
|
|
rowCount: 1,
|
|
rows: [
|
|
{
|
|
household_id: 1,
|
|
store_location_id: 2,
|
|
household_store_item_id: 55,
|
|
item_type: "dairy",
|
|
item_group: "Milk",
|
|
zone: "Dairy & Refrigerated",
|
|
zone_id: 12,
|
|
confidence: 1,
|
|
source: "user",
|
|
},
|
|
],
|
|
});
|
|
|
|
const result = await List.upsertClassification(1, 2, 55, {
|
|
item_type: "dairy",
|
|
item_group: "Milk",
|
|
zone: "Dairy & Refrigerated",
|
|
confidence: 1,
|
|
source: "user",
|
|
});
|
|
|
|
expect(result).toEqual(
|
|
expect.objectContaining({
|
|
household_id: 1,
|
|
store_location_id: 2,
|
|
household_store_item_id: 55,
|
|
item_type: "dairy",
|
|
})
|
|
);
|
|
expect(pool.query).toHaveBeenLastCalledWith(
|
|
expect.stringContaining("ON CONFLICT (household_id, store_location_id, household_store_item_id)"),
|
|
[1, 2, 55, "dairy", "Milk", "Dairy & Refrigerated", 12, 1, "user"]
|
|
);
|
|
});
|
|
});
|