toMatchArray(['days_left' => 2, 'light' => 'red']); // balance 4000 (< red_floor 5000), spend 100 → days 40, но балансtoBe('red'); // balance 12000 (< amber 15000), days большой → amber expect(BalanceHealth::evaluate(12000, 100, 5000, 15000)['light'])->toBe('amber'); // balance 100000, spend 100 → days 1000, выше порогов → green expect(BalanceHealth::evaluate(100000, 100, 5000, 15000)['light'])->toBe('green'); // нет данных о расходе → days_left null, светофор только по порогам expect(BalanceHealth::evaluate(100000, null, 5000, 15000))->toMatchArray(['days_left' => null, 'light' => 'green']); // граница: ровно 7 дней — НЕ amber (порог «< 7»); 6 дней — amber expect(BalanceHealth::evaluate(700, 100, 0, 0)['light'])->toBe('green'); expect(BalanceHealth::evaluate(600, 100, 0, 0)['light'])->toBe('amber'); // отрицательный баланс (YC в минусе) → red expect(BalanceHealth::evaluate(-540, null, 1000, 5000))->toMatchArray(['days_left' => null, 'light' => 'red']); // отрицательный баланс + известный расход → days_left КЛАМПИТСЯ к 0 (не «−1 дн.») expect(BalanceHealth::evaluate(-591.76, 600, 1000, 5000))->toMatchArray(['days_left' => 0, 'light' => 'red']); });