MeshiTrack/packages/api/src/modules/recipes/unit-conversion.service.test.ts

133 lines
4.4 KiB
TypeScript
Raw Normal View History

2026-05-14 14:47:23 +09:00
import { describe, it, expect } from 'vitest';
import { toMetric } from './unit-conversion.service.js';
describe('toMetric', () => {
describe('metric pass-through', () => {
it('passes g through unchanged', () => {
const r = toMetric(100, 'g', 'g');
expect(r).toEqual({ ok: true, quantity: 100, unit: 'g' });
});
it('passes ml through unchanged', () => {
const r = toMetric(250, 'ml', 'ml');
expect(r).toEqual({ ok: true, quantity: 250, unit: 'ml' });
});
it('passes piece through unchanged', () => {
const r = toMetric(2, 'piece', 'piece');
expect(r).toEqual({ ok: true, quantity: 2, unit: 'piece' });
});
it('passes slice through unchanged', () => {
const r = toMetric(3, 'slice', 'slice');
expect(r).toEqual({ ok: true, quantity: 3, unit: 'slice' });
});
});
describe('mass conversions', () => {
it('converts oz to g for a g-product', () => {
const r = toMetric(1, 'oz', 'g');
expect(r).toEqual({ ok: true, quantity: 28.35, unit: 'g' });
});
it('converts lb to g for a g-product', () => {
const r = toMetric(1, 'lb', 'g');
expect(r).toEqual({ ok: true, quantity: 453.592, unit: 'g' });
});
it('converts oz to ml using density for a ml-product', () => {
// 1 oz = 28.3495 g; density 1.03 g/ml → 27.524... ml
const r = toMetric(1, 'oz', 'ml', 1.03);
expect(r.ok).toBe(true);
if (r.ok) {
expect(r.unit).toBe('ml');
expect(r.quantity).toBeCloseTo(27.524, 2);
}
});
it('returns MISSING_DENSITY for oz → ml when density absent', () => {
const r = toMetric(1, 'oz', 'ml');
expect(r).toMatchObject({ ok: false, code: 'MISSING_DENSITY' });
});
it('returns INCOMPATIBLE_UNITS for oz → piece', () => {
const r = toMetric(1, 'oz', 'piece');
expect(r).toMatchObject({ ok: false, code: 'INCOMPATIBLE_UNITS' });
});
});
describe('volume conversions', () => {
it('converts tsp to ml for a ml-product', () => {
const r = toMetric(1, 'tsp', 'ml');
expect(r).toEqual({ ok: true, quantity: 4.929, unit: 'ml' });
});
it('converts tbsp to ml for a ml-product', () => {
const r = toMetric(1, 'tbsp', 'ml');
expect(r).toEqual({ ok: true, quantity: 14.787, unit: 'ml' });
});
it('converts fl_oz to ml for a ml-product', () => {
const r = toMetric(1, 'fl_oz', 'ml');
expect(r).toEqual({ ok: true, quantity: 29.574, unit: 'ml' });
});
it('converts cup to ml for a ml-product', () => {
const r = toMetric(1, 'cup', 'ml');
expect(r).toEqual({ ok: true, quantity: 236.588, unit: 'ml' });
});
it('converts cup to g using density for a g-product', () => {
// 1 cup = 236.588 ml; density 1.05 g/ml → 248.417 g
const r = toMetric(1, 'cup', 'g', 1.05);
expect(r.ok).toBe(true);
if (r.ok) {
expect(r.unit).toBe('g');
expect(r.quantity).toBeCloseTo(248.417, 2);
}
});
it('returns MISSING_DENSITY for cup → g when density absent', () => {
const r = toMetric(1, 'cup', 'g');
expect(r).toMatchObject({ ok: false, code: 'MISSING_DENSITY' });
});
it('returns INCOMPATIBLE_UNITS for cup → piece', () => {
const r = toMetric(1, 'cup', 'piece');
expect(r).toMatchObject({ ok: false, code: 'INCOMPATIBLE_UNITS' });
});
});
describe('mass to ml cross-conversion', () => {
it('converts oz to ml using density', () => {
// 1 oz = 28.3495 g; density 0.9 g/ml → 28.3495 / 0.9 = 31.499... ml
const r = toMetric(1, 'oz', 'ml', 0.9);
expect(r.ok).toBe(true);
if (r.ok) {
expect(r.unit).toBe('ml');
expect(r.quantity).toBeCloseTo(31.499, 1);
}
});
it('returns MISSING_DENSITY for oz → ml when density absent', () => {
const r = toMetric(1, 'oz', 'ml');
expect(r).toMatchObject({ ok: false, code: 'MISSING_DENSITY' });
});
it('returns INCOMPATIBLE_UNITS for oz → piece', () => {
const r = toMetric(1, 'oz', 'piece');
expect(r).toMatchObject({ ok: false, code: 'INCOMPATIBLE_UNITS' });
});
});
describe('unknown unit', () => {
it('returns INCOMPATIBLE_UNITS for unknown unit', () => {
const r = toMetric(1, 'gallon' as never, 'g');
expect(r).toMatchObject({ ok: false, code: 'INCOMPATIBLE_UNITS' });
if (!r.ok) {
expect(r.message).toContain('Unknown unit');
}
});
});
});