Files
doormilxpress_astryx/tests/lib/SkillRegistry.test.js

83 lines
3.6 KiB
JavaScript

import { SkillRegistry, DEFAULT_SKILLS } from '@/lib/assistant/skills/SkillRegistry';
/**
* The SkillRegistry joins the rules (code) with the settings (the backend
* agent registry, /admin/ai/skills). Rows below are shaped exactly like that
* endpoint's response.
*/
const row = (skillid, enabled, thresholds = {}) => ({ skillid, enabled, thresholds });
describe('SkillRegistry', () => {
beforeEach(() => {
SkillRegistry.clearRegistryConfig();
});
it('registers the eight built-in logistics skills', () => {
const ids = SkillRegistry.getAllSkills().map((s) => s.id);
expect(ids).toHaveLength(8);
expect(ids).toEqual(DEFAULT_SKILLS.map((s) => s.id));
expect(ids).toContain('skill_sla_guardian');
expect(ids).toContain('skill_rider_battery_safety');
});
it('runs on code defaults until the registry answers, and says so', () => {
expect(SkillRegistry.getSource()).toBe('defaults');
const sla = SkillRegistry.getSkill('skill_sla_guardian');
expect(sla.enabled).toBe(true);
expect(sla.effectiveThresholds.slaRiskWindowMin.currentValue).toBe(45);
});
it('takes enabled and thresholds from the registry', () => {
SkillRegistry.applyRegistryConfig([
row('skill_fleet_balancer', false),
row('skill_sla_guardian', true, { slaRiskWindowMin: 30 })
]);
expect(SkillRegistry.getSource()).toBe('registry');
expect(SkillRegistry.getSkill('skill_fleet_balancer').enabled).toBe(false);
expect(SkillRegistry.getSkill('skill_sla_guardian').effectiveThresholds.slaRiskWindowMin.currentValue).toBe(30);
// A threshold the registry did not send keeps its default.
expect(SkillRegistry.getSkill('skill_sla_guardian').effectiveThresholds.unassignedAgingMin.currentValue).toBe(60);
});
it('can switch on a skill that is off by default', () => {
SkillRegistry.applyRegistryConfig([row('skill_cash_exposure', true)]);
expect(SkillRegistry.getSkill('skill_cash_exposure').enabled).toBe(true);
});
it('ignores an out-of-range stored value rather than running on it', () => {
SkillRegistry.applyRegistryConfig([row('skill_doorstep_stall', true, { arrivedStalledMin: 999 })]);
expect(SkillRegistry.getSkill('skill_doorstep_stall').effectiveThresholds.arrivedStalledMin.currentValue).toBe(20);
});
it('ignores registry rows for skills this console does not implement', () => {
SkillRegistry.applyRegistryConfig([row('stall_response', false), row('custom_night_shift_watch', true)]);
expect(SkillRegistry.getAllSkills()).toHaveLength(8);
expect(SkillRegistry.getSkill('stall_response')).toBeUndefined();
});
it('goes back to defaults when the registry is lost', () => {
SkillRegistry.applyRegistryConfig([row('skill_sla_guardian', false, { slaRiskWindowMin: 15 })]);
SkillRegistry.clearRegistryConfig();
const sla = SkillRegistry.getSkill('skill_sla_guardian');
expect(SkillRegistry.getSource()).toBe('defaults');
expect(sla.enabled).toBe(true);
expect(sla.effectiveThresholds.slaRiskWindowMin.currentValue).toBe(45);
});
it('keeps nothing in browser storage', () => {
localStorage.clear();
SkillRegistry.applyRegistryConfig([row('skill_sla_guardian', false)]);
expect(localStorage.length).toBe(0);
});
it('notifies subscribers when the registry settings change', () => {
const listener = jest.fn();
const unsubscribe = SkillRegistry.subscribe(listener);
SkillRegistry.applyRegistryConfig([row('skill_doorstep_stall', false)]);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener.mock.calls[0][0].find((s) => s.id === 'skill_doorstep_stall').enabled).toBe(false);
unsubscribe();
});
});