Add inactive item fallback for dashboard change feed lookups
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -16,6 +16,7 @@ vi.mock('../../src/api/client.js', () => ({
|
||||
const {
|
||||
adjustStockEntry,
|
||||
applyItemUpsert,
|
||||
getStockEntry,
|
||||
listGroupedStockEntries,
|
||||
listKitchenChanges,
|
||||
listStockEntries,
|
||||
@@ -125,6 +126,35 @@ describe('api/stock', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('getStockEntry fetches item without allow_inactive by default', async () => {
|
||||
apiRequestMock.mockResolvedValueOnce({ uuid_b64: 'item-1', name: 'Milk' });
|
||||
|
||||
const result = await getStockEntry({ config: { database: 'db' } }, 'item-1');
|
||||
|
||||
expect(result).toEqual({ uuid_b64: 'item-1', name: 'Milk' });
|
||||
expect(apiRequestMock).toHaveBeenCalledWith(
|
||||
{ config: { database: 'db' } },
|
||||
'kitchen/items/item-1',
|
||||
);
|
||||
});
|
||||
|
||||
it('getStockEntry forwards allow_inactive when requested', async () => {
|
||||
apiRequestMock.mockResolvedValueOnce({ uuid_b64: 'item-2', active: false });
|
||||
|
||||
const result = await getStockEntry(
|
||||
{ config: { database: 'db' } },
|
||||
'item-2',
|
||||
{ allowInactive: true },
|
||||
);
|
||||
|
||||
expect(result).toEqual({ uuid_b64: 'item-2', active: false });
|
||||
expect(apiRequestMock).toHaveBeenCalledWith(
|
||||
{ config: { database: 'db' } },
|
||||
'kitchen/items/item-2',
|
||||
{ query: { allow_inactive: 1 } },
|
||||
);
|
||||
});
|
||||
|
||||
it('listKitchenChanges returns normalized changes payload', async () => {
|
||||
apiRequestMock.mockResolvedValueOnce({
|
||||
since: 'cursor-1',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
const listKitchenChangesMock = vi.fn();
|
||||
const getStockEntryMock = vi.fn();
|
||||
@@ -16,6 +16,12 @@ vi.mock('../../../src/api/locations.js', () => ({
|
||||
const { dashboardPageData, renderDashboardPage } = await import('../../../src/features/dashboard/dashboard-page.js');
|
||||
|
||||
describe('features/dashboard/dashboard-page', () => {
|
||||
beforeEach(() => {
|
||||
listKitchenChangesMock.mockReset();
|
||||
getStockEntryMock.mockReset();
|
||||
fetchLocationsMock.mockReset();
|
||||
});
|
||||
|
||||
it('renders dashboard with recent changes section', () => {
|
||||
const html = renderDashboardPage();
|
||||
expect(html).toContain('Recent changes');
|
||||
@@ -107,6 +113,50 @@ describe('features/dashboard/dashboard-page', () => {
|
||||
expect(getStockEntryMock).toHaveBeenCalledWith(expect.anything(), 'item-uuid-1');
|
||||
});
|
||||
|
||||
it('retries stock event item lookup with allowInactive after 404', async () => {
|
||||
listKitchenChangesMock.mockResolvedValueOnce({
|
||||
since: null,
|
||||
nextCursor: null,
|
||||
changes: [{
|
||||
type: 'stock',
|
||||
action: 'upsert',
|
||||
timestamp: '2026-04-10T10:00:00Z',
|
||||
stock: {
|
||||
item_uuid_b64: 'item-uuid-2',
|
||||
quantity: 1,
|
||||
uom_symbol: 'pcs',
|
||||
},
|
||||
}],
|
||||
});
|
||||
getStockEntryMock
|
||||
.mockRejectedValueOnce(Object.assign(new Error('Not found'), { status: 404 }))
|
||||
.mockResolvedValueOnce({
|
||||
uuid_b64: 'item-uuid-2',
|
||||
name: 'Archived pasta',
|
||||
stock_type: 'measured',
|
||||
});
|
||||
fetchLocationsMock.mockResolvedValueOnce({ flat: [] });
|
||||
|
||||
const store = {
|
||||
isConnected: true,
|
||||
setActiveKitchen: vi.fn(),
|
||||
addAlert: vi.fn(),
|
||||
};
|
||||
const data = dashboardPageData(store);
|
||||
|
||||
await data.refreshChanges();
|
||||
|
||||
expect(getStockEntryMock).toHaveBeenNthCalledWith(1, store, 'item-uuid-2');
|
||||
expect(getStockEntryMock).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
store,
|
||||
'item-uuid-2',
|
||||
{ allowInactive: true },
|
||||
);
|
||||
expect(data.changeHeadline(data.recentChanges[0])).toBe('Stock saved: Archived pasta');
|
||||
expect(data.changeStateLine(data.recentChanges[0])).toContain('Quantity: 1 pcs');
|
||||
});
|
||||
|
||||
it('keeps empty state when API returns no changes', async () => {
|
||||
listKitchenChangesMock.mockResolvedValueOnce({
|
||||
since: null,
|
||||
|
||||
Reference in New Issue
Block a user