1import { describe, it, expect } from 'vitest';2import { initFromPolicy, initGeneratorState, handleLengthChange } from '../generator-policy';34describe('generator site policy constraints', () => {56 describe('Case 1 — no policy', () => {7 it('defaults to 64 when unconstrained and fresh', () => {8 const r = initFromPolicy(null, { currentLength: 64, userHasAdjusted: false });9 expect(r.length).toBe(64);10 });1112 it('preserves user length when no policy and user adjusted', () => {13 const r = initFromPolicy(null, { currentLength: 80, userHasAdjusted: true });14 expect(r.length).toBe(80);15 });1617 it('shows no constraint note', () => {18 const r = initFromPolicy(null, { currentLength: 64, userHasAdjusted: false });19 expect(r.constraintNote).toBeFalsy();20 });2122 it('leaves slider bounds at defaults', () => {23 const r = initFromPolicy(null, { currentLength: 64, userHasAdjusted: false });24 expect(r.sliderMin).toBe(8);25 expect(r.sliderMax).toBe(128);26 });27 });2829 describe('Case 2 — site maxLength, fresh open', () => {30 it('snaps to site maxLength', () => {31 const r = initFromPolicy(32 { maxLength: 100 },33 { currentLength: 64, userHasAdjusted: false },34 );35 expect(r.length).toBe(100);36 });3738 it('shows constraint note containing maxLength', () => {39 const r = initFromPolicy(40 { maxLength: 100 },41 { currentLength: 64, userHasAdjusted: false },42 );43 expect(r.constraintNote).toMatch(/100/);44 });4546 it('sets sliderMax to site maxLength', () => {47 const r = initFromPolicy(48 { maxLength: 100 },49 { currentLength: 64, userHasAdjusted: false },50 );51 expect(r.sliderMax).toBe(100);52 });53 });5455 describe('Case 3 — user above site max', () => {56 it('snaps DOWN to site max', () => {57 const r = initFromPolicy(58 { maxLength: 50 },59 { currentLength: 80, userHasAdjusted: true },60 );61 expect(r.length).toBe(50);62 });6364 it('shows constraint note after forced snap down', () => {65 const r = initFromPolicy(66 { maxLength: 50 },67 { currentLength: 80, userHasAdjusted: true },68 );69 expect(r.constraintNote).toBeTruthy();70 });71 });7273 describe('Case 4 — user below site max', () => {74 it('keeps user length when within bounds', () => {75 const r = initFromPolicy(76 { maxLength: 100 },77 { currentLength: 20, userHasAdjusted: true },78 );79 expect(r.length).toBe(20);80 });8182 it('shows no constraint note when within bounds', () => {83 const r = initFromPolicy(84 { maxLength: 100 },85 { currentLength: 20, userHasAdjusted: true },86 );87 expect(r.constraintNote).toBeFalsy();88 });89 });9091 describe('Case 5 — site minLength', () => {92 it('snaps UP to site minLength', () => {93 const r = initFromPolicy(94 { minLength: 12 },95 { currentLength: 8, userHasAdjusted: false },96 );97 expect(r.length).toBe(12);98 });99100 it('shows constraint note containing minLength', () => {101 const r = initFromPolicy(102 { minLength: 12 },103 { currentLength: 8, userHasAdjusted: false },104 );105 expect(r.constraintNote).toMatch(/12/);106 });107108 it('sets sliderMin to site minLength', () => {109 const r = initFromPolicy(110 { minLength: 12 },111 { currentLength: 8, userHasAdjusted: false },112 );113 expect(r.sliderMin).toBe(12);114 });115116 it('does not snap up when already above minLength', () => {117 const r = initFromPolicy(118 { minLength: 12 },119 { currentLength: 20, userHasAdjusted: true },120 );121 expect(r.length).toBe(20);122 });123 });124125 describe('Case 6 — both min and max', () => {126 it('snaps to min when below range', () => {127 const r = initFromPolicy(128 { minLength: 8, maxLength: 32 },129 { currentLength: 4, userHasAdjusted: false },130 );131 expect(r.length).toBe(8);132 });133134 it('snaps to max when above range', () => {135 const r = initFromPolicy(136 { minLength: 8, maxLength: 32 },137 { currentLength: 64, userHasAdjusted: true },138 );139 expect(r.length).toBe(32);140 });141142 it('keeps user length when within range', () => {143 const r = initFromPolicy(144 { minLength: 8, maxLength: 32 },145 { currentLength: 20, userHasAdjusted: true },146 );147 expect(r.length).toBe(20);148 });149150 it('defaults to maxLength on fresh open', () => {151 const r = initFromPolicy(152 { minLength: 8, maxLength: 32 },153 { currentLength: 64, userHasAdjusted: false },154 );155 expect(r.length).toBe(32);156 });157158 it('sets both sliderMin and sliderMax', () => {159 const r = initFromPolicy(160 { minLength: 8, maxLength: 32 },161 { currentLength: 20, userHasAdjusted: false },162 );163 expect(r.sliderMin).toBe(8);164 expect(r.sliderMax).toBe(32);165 });166 });167168 describe('userHasAdjusted flag', () => {169 it('is false on fresh generator open', () => {170 const state = initGeneratorState();171 expect(state.userHasAdjusted).toBe(false);172 });173174 it('becomes true after slider move', () => {175 let state = initGeneratorState();176 state = handleLengthChange(state, 80);177 expect(state.userHasAdjusted).toBe(true);178 });179180 it('false: policy snap applies', () => {181 const r = initFromPolicy(182 { maxLength: 100 },183 { currentLength: 64, userHasAdjusted: false },184 );185 expect(r.length).toBe(100);186 });187188 it('true: policy only enforces hard bounds', () => {189 const r = initFromPolicy(190 { maxLength: 100 },191 { currentLength: 30, userHasAdjusted: true },192 );193 expect(r.length).toBe(30);194 });195 });196});