import type { EvidenceLookup } from '../evidence-lookup'; import { renderSuggestion } from '../suggestion-texts'; import type { SuggestionEvidence } from '../suggestion.types'; import { RULE_TEXTS } from './rule-texts'; const lookup: EvidenceLookup = { colonyCode: (id) => (id === 'gone' ? null : 'LWG'), queenCode: () => null, treatmentProduct: (id) => (id === 'gone' ? null : 'Ameisensäure'), apiaryName: () => null, stockItemName: () => 'Gläser 500 g', }; const TODAY = '2026-10-14'; function render( reasonCode: string, evidence: SuggestionEvidence, intent: 'VARROA_TREAT' | 'FOLLOW_UP' | 'STOCK_REORDER' = 'FOLLOW_UP', ) { return renderSuggestion( { reasonCode, evidence: evidence as never, intent }, lookup, TODAY, ); } describe('rule texts', () => { it('has a template for every reason code of the rule suggestions', () => { expect(Object.keys(RULE_TEXTS).sort()).toEqual( [ 'COLONY_HEALTH_CRITICAL', 'FEEDING_FOLLOW_UP', 'FEED_STATUS_CRITICAL', 'QUEENLESS_NO_EGGS', 'RAW_MATERIAL_LOW', 'STOCK_ITEM_LOW', 'SWARM_MOOD_HIGH', 'TREATMENT_FOLLOW_UP', 'VARROA_RED', ].sort(), ); }); it('VARROA_RED names rate, day and limit with the colony code', () => { expect(render('VARROA_RED', RULE_TEXTS.VARROA_RED.example)).toEqual({ title: 'Behandlung prüfen', reasons: ['12,4 Milben pro Tag am 10.05.', 'Grenze: 10 (LWG).'], }); }); it('VARROA_RED words a percentage method in percent', () => { const { reasons } = render('VARROA_RED', { colonyId: 'c', measuredOn: '2026-07-10', value: 6, redAbove: 5, unit: 'PERCENT', }); expect(reasons).toEqual(['6 % Befall am 10.07.', 'Grenze: 5 % (LWG).']); }); it('QUEENLESS_NO_EGGS and the inspection rules name the day and the colony', () => { expect( render('QUEENLESS_NO_EGGS', RULE_TEXTS.QUEENLESS_NO_EGGS.example).reasons, ).toEqual(['Königin nicht gesehen, keine Eier am 05.05.']); expect( render('FEED_STATUS_CRITICAL', RULE_TEXTS.FEED_STATUS_CRITICAL.example) .reasons, ).toEqual(['Futterstatus kritisch am 05.05.']); }); it('STOCK_ITEM_LOW names the item and the minimum', () => { expect( render('STOCK_ITEM_LOW', RULE_TEXTS.STOCK_ITEM_LOW.example).reasons, ).toEqual(['Gläser 500 g: noch 2 auf Lager, Mindestbestand 5.']); }); it('RAW_MATERIAL_LOW names the kind in German', () => { expect( render('RAW_MATERIAL_LOW', RULE_TEXTS.RAW_MATERIAL_LOW.example).reasons, ).toEqual(['Bienenwachs: noch 400 g auf Lager, Mindestmenge 1.000 g.']); }); it('TREATMENT_FOLLOW_UP names the product, or none when the treatment is gone', () => { expect( render('TREATMENT_FOLLOW_UP', RULE_TEXTS.TREATMENT_FOLLOW_UP.example) .reasons, ).toEqual(['Nach Behandlung mit Ameisensäure am 10.08.']); expect( render('TREATMENT_FOLLOW_UP', { colonyId: 'gone', treatmentId: 'gone', endedOn: '2026-08-10', }).reasons, ).toEqual(['Nach der Behandlung am 10.08.']); }); it('survives evidence without its optional parts', () => { for (const [reasonCode, template] of Object.entries(RULE_TEXTS)) { const { title, reasons } = render(reasonCode, {}); expect(title).not.toBe(''); expect(reasons.length).toBeLessThanOrEqual(2); expect(template.ruleKey).toBeTruthy(); } }); });