/**
* The "Last dried" column (#2863): shown by default, with the temperature and
* hours of the run when they are known.
*/
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { screen, waitFor } from '@testing-library/react';
import { render } from '../utils';
import InventoryPageRouter from '../../pages/InventoryPage';
import { http, HttpResponse } from 'msw';
import { server } from '../mocks/server';
const BASE = {
material: 'PLA',
subtype: 'Basic',
color_name: 'Red',
rgba: 'FF0000FF',
label_weight: 1000,
core_weight: 250,
weight_used: 100,
slicer_filament: null,
slicer_filament_name: null,
nozzle_temp_min: 220,
nozzle_temp_max: 240,
note: null,
added_full: null,
last_used: null,
encode_time: null,
tag_uid: null,
tray_uuid: null,
data_origin: null,
tag_type: null,
archived_at: null,
created_at: '2025-01-01T00:00:00Z',
updated_at: '2025-01-01T00:00:00Z',
k_profiles: [],
cost_per_kg: null,
last_scale_weight: null,
last_weighed_at: null,
storage_location: null,
category: null,
low_stock_threshold_pct: null,
weight_locked: false,
};
const SPOOLS = [
{ ...BASE, id: 1, brand: 'AlphaBrand', last_dried_at: '2026-09-01T12:00:00', last_dried_temp: 55, last_dried_hours: 7.5 },
{ ...BASE, id: 2, brand: 'BetaBrand', last_dried_at: '2026-09-02T12:00:00', last_dried_temp: null, last_dried_hours: null },
{ ...BASE, id: 3, brand: 'GammaBrand', last_dried_at: null },
];
function setupHandlers() {
server.use(
http.get('/api/v1/settings/', () => HttpResponse.json({ currency: 'USD', low_stock_threshold: 20.0, language: 'en' })),
http.get('/api/v1/settings/spoolman', () =>
HttpResponse.json({ spoolman_enabled: 'false', spoolman_url: '' })
),
http.get('/api/v1/inventory/spools', () => HttpResponse.json(SPOOLS)),
http.get('/api/v1/inventory/assignments', () => HttpResponse.json([])),
http.get('/api/v1/inventory/catalog', () => HttpResponse.json([])),
http.get('/api/v1/inventory/color-catalog', () => HttpResponse.json([])),
http.get('/api/v1/inventory/colors', () => HttpResponse.json([])),
http.get('/api/v1/inventory/spool-catalog', () => HttpResponse.json([])),
http.get('/api/v1/inventory/locations', () => HttpResponse.json([])),
http.get('/api/v1/printers/', () => HttpResponse.json([])),
);
}
function row(brand: string): HTMLElement {
const found = Array.from(document.querySelectorAll('tbody tr')).find((r) => r.textContent?.includes(brand));
if (!found) throw new Error(`no row for ${brand}`);
return found as HTMLElement;
}
describe('InventoryPage last dried column', () => {
beforeEach(() => {
setupHandlers();
vi.mocked(localStorage.getItem).mockReturnValue(null);
});
it('is visible by default', async () => {
render();
await waitFor(() => expect(screen.getByRole('columnheader', { name: /Last dried/ })).toBeInTheDocument());
});
it('shows the temperature and hours of the run when known', async () => {
render();
await waitFor(() => expect(row('AlphaBrand')).toHaveTextContent('55°C · 7.5h'));
expect(row('BetaBrand')).not.toHaveTextContent('°C');
});
it('sorts by the date', async () => {
vi.mocked(localStorage.getItem).mockImplementation((key) =>
key === 'bambuddy-inventory-sort' ? '{"column":"last_dried","direction":"desc"}' : null,
);
render();
await waitFor(() => {
const brands = Array.from(document.querySelectorAll('tbody tr')).map((r) => r.textContent ?? '');
expect(brands.findIndex((t) => t.includes('BetaBrand'))).toBeLessThan(
brands.findIndex((t) => t.includes('AlphaBrand')),
);
});
});
});