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 item metadata when creating a new household list item", async () => { pool.query .mockResolvedValueOnce({ rowCount: 0, rows: [] }) .mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55 }] }) .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, itemName: "milk", isNew: true, }); expect(pool.query).toHaveBeenNthCalledWith( 1, "SELECT id FROM items WHERE name ILIKE $1", ["milk"] ); expect(pool.query).toHaveBeenNthCalledWith( 2, "INSERT INTO items (name) VALUES ($1) RETURNING id", ["milk"] ); }); test("returns item metadata when updating an existing household list item", async () => { pool.query .mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 55 }] }) .mockResolvedValueOnce({ rowCount: 1, rows: [{ id: 88, bought: false }] }) .mockResolvedValueOnce({ rowCount: 1, rows: [] }); const result = await List.addOrUpdateItem(1, 2, "Milk", 4, 7); expect(result).toEqual({ listId: 88, itemId: 55, itemName: "milk", isNew: false, }); expect(pool.query).toHaveBeenNthCalledWith( 3, expect.stringContaining("UPDATE household_lists"), [4, 88] ); }); }); describe("list.model.v2 classification helpers", () => { beforeEach(() => { pool.query.mockReset(); }); test("gets classification using household, store, and 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("WHERE household_id = $1 AND store_id = $2 AND item_id = $3"), [1, 2, 55] ); }); test("upserts classification using store-scoped conflict target", async () => { pool.query.mockResolvedValueOnce({ rowCount: 1, rows: [ { household_id: 1, store_id: 2, item_id: 55, item_type: "dairy", item_group: "Milk", zone: "Dairy & Refrigerated", 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_id: 2, item_id: 55, item_type: "dairy", }) ); expect(pool.query).toHaveBeenCalledWith( expect.stringContaining("ON CONFLICT (household_id, store_id, item_id)"), [1, 2, 55, "dairy", "Milk", "Dairy & Refrigerated", 1, "user"] ); }); });