Add scanner utility, modal, and stock scan page implementation #9

Merged
bblaz merged 2 commits from codex/plan-item-scanning-flows into main 2026-05-01 21:36:41 +00:00
2 changed files with 14 additions and 14 deletions
Showing only changes of commit e63c8a2770 - Show all commits
+2 -2
View File
@@ -299,10 +299,10 @@ describe('label create upsert-first submit', () => {
await data.create(); await data.create();
expect(data.printIssue).toBe('Printer is unavailable.'); expect(data.printIssue).toBe('Beans was created, but printing failed: Printer is unavailable.');
expect(addAlert).toHaveBeenCalledWith({ expect(addAlert).toHaveBeenCalledWith({
type: 'warning', type: 'warning',
message: 'Beans was created, but printing has an issue: Printer is unavailable.', message: 'Beans was created, but printing failed: Printer is unavailable.',
}); });
expect(localStorageMock.setItem).toHaveBeenCalled(); expect(localStorageMock.setItem).toHaveBeenCalled();
}); });
+12 -12
View File
@@ -1,11 +1,11 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
const useStockItemMock = vi.fn(); const markStockGoneMock = vi.fn();
const getStockEntryMock = vi.fn(); const getStockEntryMock = vi.fn();
const listGroupedStockEntriesMock = vi.fn(); const listGroupedStockEntriesMock = vi.fn();
vi.mock('../../../src/api/stock.js', () => ({ vi.mock('../../../src/api/stock.js', () => ({
useStockItem: (...args) => useStockItemMock(...args), markStockGone: (...args) => markStockGoneMock(...args),
getStockEntry: (...args) => getStockEntryMock(...args), getStockEntry: (...args) => getStockEntryMock(...args),
adjustStockEntry: vi.fn(), adjustStockEntry: vi.fn(),
lookupItemDetails: vi.fn(), lookupItemDetails: vi.fn(),
@@ -24,7 +24,7 @@ const { stockListPageData } = await import('../../../src/features/stock/stock-li
describe('stock mark-gone behavior', () => { describe('stock mark-gone behavior', () => {
beforeEach(() => { beforeEach(() => {
useStockItemMock.mockReset(); markStockGoneMock.mockReset();
getStockEntryMock.mockReset(); getStockEntryMock.mockReset();
listGroupedStockEntriesMock.mockReset(); listGroupedStockEntriesMock.mockReset();
globalThis.window = { globalThis.window = {
@@ -39,15 +39,15 @@ describe('stock mark-gone behavior', () => {
delete globalThis.window; delete globalThis.window;
}); });
it('stock detail markGone uses /use and shows info for already gone', async () => { it('stock detail markGone posts gone event and shows info for already gone', async () => {
useStockItemMock.mockResolvedValueOnce({ status: 'already_gone' }); markStockGoneMock.mockResolvedValueOnce({ status: 'already_gone' });
const addAlert = vi.fn(); const addAlert = vi.fn();
const data = stockDetailPageData({ addAlert }); const data = stockDetailPageData({ addAlert });
data.entry = { uuid_b64: 'item-1', name: 'Rice' }; data.entry = { uuid_b64: 'item-1', name: 'Rice' };
await data.markGone(); await data.markGone();
expect(useStockItemMock).toHaveBeenCalledWith({ addAlert }, 'item-1'); expect(markStockGoneMock).toHaveBeenCalledWith({ addAlert }, 'item-1', 'consumed');
expect(addAlert).toHaveBeenCalledWith({ expect(addAlert).toHaveBeenCalledWith({
type: 'info', type: 'info',
message: 'Rice was already out of stock.', message: 'Rice was already out of stock.',
@@ -55,8 +55,8 @@ describe('stock mark-gone behavior', () => {
expect(globalThis.window.__loncApp.navigate).toHaveBeenCalledWith('/stock'); expect(globalThis.window.__loncApp.navigate).toHaveBeenCalledWith('/stock');
}); });
it('stock list markGone removes entry and uses /use path', async () => { it('stock list markGone removes entry and posts gone event', async () => {
useStockItemMock.mockResolvedValueOnce({ status: 'used' }); markStockGoneMock.mockResolvedValueOnce({ status: 'ok' });
const addAlert = vi.fn(); const addAlert = vi.fn();
const data = stockListPageData({ addAlert, isConnected: false }); const data = stockListPageData({ addAlert, isConnected: false });
data.entries = [{ id: 1, uuid_b64: 'item-1', name: 'Flour' }]; data.entries = [{ id: 1, uuid_b64: 'item-1', name: 'Flour' }];
@@ -65,16 +65,16 @@ describe('stock mark-gone behavior', () => {
await data.markGone(data.entries[0]); await data.markGone(data.entries[0]);
expect(useStockItemMock).toHaveBeenCalledWith({ addAlert, isConnected: false }, 'item-1'); expect(markStockGoneMock).toHaveBeenCalledWith({ addAlert, isConnected: false }, 'item-1', 'consumed');
expect(data.entries).toEqual([]); expect(data.entries).toEqual([]);
expect(addAlert).toHaveBeenCalledWith({ expect(addAlert).toHaveBeenCalledWith({
type: 'success', type: 'success',
message: 'Flour was marked gone and removed from the list.', message: 'Flour was marked used and removed from the list.',
}); });
}); });
it('stock list grouped markGone removes item from grouped and flat collections', async () => { it('stock list grouped markGone removes item from grouped and flat collections', async () => {
useStockItemMock.mockResolvedValueOnce({ status: 'used' }); markStockGoneMock.mockResolvedValueOnce({ status: 'ok' });
listGroupedStockEntriesMock.mockResolvedValueOnce([]); listGroupedStockEntriesMock.mockResolvedValueOnce([]);
const addAlert = vi.fn(); const addAlert = vi.fn();
const store = { addAlert, isConnected: true }; const store = { addAlert, isConnected: true };
@@ -127,7 +127,7 @@ describe('stock mark-gone behavior', () => {
expect(data.groupedEntries).toEqual([]); expect(data.groupedEntries).toEqual([]);
expect(addAlert).toHaveBeenCalledWith({ expect(addAlert).toHaveBeenCalledWith({
type: 'success', type: 'success',
message: 'Beans was marked gone and removed from the group.', message: 'Beans was marked used and removed from the group.',
}); });
expect(listGroupedStockEntriesMock).toHaveBeenCalledTimes(1); expect(listGroupedStockEntriesMock).toHaveBeenCalledTimes(1);
expect(listGroupedStockEntriesMock).toHaveBeenCalledWith(store, { expanded: 0 }); expect(listGroupedStockEntriesMock).toHaveBeenCalledWith(store, { expanded: 0 });