| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- /**
- * Tests for inventory fill level calculation logic.
- *
- * The fill level is calculated inline in PrintersPage.tsx as:
- * if (sp && sp.label_weight > 0 && sp.weight_used != null)
- * → Math.round(Math.max(0, sp.label_weight - sp.weight_used) / sp.label_weight * 100)
- * else → null
- *
- * These tests validate the calculation logic directly, particularly the
- * fix for weight_used == null (brand new spools) and weight_used == 0.
- */
- import { describe, it, expect } from 'vitest';
- /**
- * Mirrors the inline inventoryFill calculation from PrintersPage.tsx.
- * Extracted here for testability.
- */
- function computeInventoryFill(spool: { label_weight: number; weight_used: number | null } | null): number | null {
- const sp = spool;
- if (sp && sp.label_weight > 0 && sp.weight_used != null) {
- return Math.round(Math.max(0, sp.label_weight - sp.weight_used) / sp.label_weight * 100);
- }
- return null;
- }
- describe('inventoryFill calculation', () => {
- it('returns 100% for brand new spool with weight_used = 0', () => {
- expect(computeInventoryFill({ label_weight: 1000, weight_used: 0 })).toBe(100);
- });
- it('returns null for brand new spool with weight_used = null', () => {
- // weight_used null means "never tracked" — we can't compute fill
- expect(computeInventoryFill({ label_weight: 1000, weight_used: null })).toBeNull();
- });
- it('returns correct percentage for partially used spool', () => {
- expect(computeInventoryFill({ label_weight: 1000, weight_used: 250 })).toBe(75);
- });
- it('returns 0% for fully used spool', () => {
- expect(computeInventoryFill({ label_weight: 1000, weight_used: 1000 })).toBe(0);
- });
- it('returns 0% when weight_used exceeds label_weight', () => {
- // Math.max(0, ...) prevents negative fill
- expect(computeInventoryFill({ label_weight: 1000, weight_used: 1200 })).toBe(0);
- });
- it('returns null when no spool data', () => {
- expect(computeInventoryFill(null)).toBeNull();
- });
- it('returns null when label_weight is 0', () => {
- expect(computeInventoryFill({ label_weight: 0, weight_used: 0 })).toBeNull();
- });
- it('rounds to nearest integer', () => {
- // 1000 - 333 = 667, 667/1000 = 66.7 → 67
- expect(computeInventoryFill({ label_weight: 1000, weight_used: 333 })).toBe(67);
- });
- });
- describe('inventoryFill: old bug — weight_used > 0 vs weight_used != null', () => {
- /**
- * The old condition was: sp.weight_used > 0
- * This caused brand-new spools (weight_used=0) to show no fill bar.
- * The fix changed it to: sp.weight_used != null
- */
- it('weight_used = 0 now shows fill (was broken with > 0 check)', () => {
- // Old: 0 > 0 = false → null (no fill bar)
- // New: 0 != null = true → 100% fill
- const result = computeInventoryFill({ label_weight: 1000, weight_used: 0 });
- expect(result).toBe(100);
- expect(result).not.toBeNull();
- });
- it('weight_used = 0.1 shows fill (small usage)', () => {
- const result = computeInventoryFill({ label_weight: 1000, weight_used: 0.1 });
- expect(result).toBe(100); // rounds to 100 since 0.1g from 1000g is negligible
- });
- });
|