mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-19 15:06:20 +00:00
dbafc97e89
Two unrelated cleanups grouped because they're both small and safe.
Dead code removal
- src/components/login/components/RegisterDialog.tsx
- src/components/login/components/ForgotDialog.tsx
- src/components/login/components/shared.ts (only consumed by the two
dialogs above)
These were the older non-Form-Actions versions of the register and
forgot-password dialogs. LoginView.tsx defines its own inline versions
that use `useActionState` + `useFormStatus` (Phase 3 of the React 19
modernization), which are the ones actually rendered. The legacy
files were already documented as dead in docs/ARCHITECTURE.md.
NewsWindow.tsx and the `components/` directory itself stay — NewsWindow
is still imported by LoginView at the bottom of the login flow.
Vitest coverage on FriendlyTime (+12 cases)
- 65 -> 77 passing tests, 5 -> 6 test files.
- LocalizeText is mocked with a deterministic stub
(`${ key }|${ amount }`) so each assertion can verify both the bucket
chosen and the rounded amount. The mock also short-circuits the
transitive renderer-SDK import, which keeps the test runner
decoupled from the renderer install state.
- Buckets covered: seconds / minutes / hours / days / months / years
for both `format` and `shortFormat`. Plus: threshold override,
key-suffix concatenation, half-hour rounding, the raw
`getLocalization` helper.
Verification
- yarn test: 6 files / 77 cases / ~2s.
- yarn eslint on the new test file: 0 errors / 0 warnings.
- yarn tsc: clean on touched files.
101 lines
3.5 KiB
TypeScript
101 lines
3.5 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
/**
|
|
* Mock LocalizeText (which transitively imports @nitrots/nitro-renderer)
|
|
* with a deterministic stub. The stub returns `key|amount` so each test
|
|
* can assert both the bucket FriendlyTime chose AND the value it computed.
|
|
*/
|
|
vi.mock('../src/api/utils/LocalizeText', () => ({
|
|
LocalizeText: (key: string, _params?: string[], replacements?: string[]) =>
|
|
`${ key }|${ replacements?.[0] ?? '' }`
|
|
}));
|
|
|
|
import { FriendlyTime } from '../src/api/utils/FriendlyTime';
|
|
|
|
const MINUTE = 60;
|
|
const HOUR = 60 * MINUTE;
|
|
const DAY = 24 * HOUR;
|
|
const MONTH = 30 * DAY;
|
|
const YEAR = 365 * DAY;
|
|
|
|
describe('FriendlyTime.format', () =>
|
|
{
|
|
it('uses the seconds bucket for small values', () =>
|
|
{
|
|
expect(FriendlyTime.format(5)).toBe('friendlytime.seconds|5');
|
|
expect(FriendlyTime.format(0)).toBe('friendlytime.seconds|0');
|
|
});
|
|
|
|
it('uses the minutes bucket once we cross 3 * 60s (default threshold)', () =>
|
|
{
|
|
expect(FriendlyTime.format(4 * MINUTE)).toBe('friendlytime.minutes|4');
|
|
expect(FriendlyTime.format(10 * MINUTE)).toBe('friendlytime.minutes|10');
|
|
});
|
|
|
|
it('uses the hours bucket above 3 * HOUR', () =>
|
|
{
|
|
expect(FriendlyTime.format(4 * HOUR)).toBe('friendlytime.hours|4');
|
|
});
|
|
|
|
it('uses the days bucket above 3 * DAY', () =>
|
|
{
|
|
expect(FriendlyTime.format(5 * DAY)).toBe('friendlytime.days|5');
|
|
});
|
|
|
|
it('uses the months bucket above 3 * MONTH', () =>
|
|
{
|
|
expect(FriendlyTime.format(4 * MONTH)).toBe('friendlytime.months|4');
|
|
});
|
|
|
|
it('uses the years bucket above 3 * YEAR', () =>
|
|
{
|
|
expect(FriendlyTime.format(4 * YEAR)).toBe('friendlytime.years|4');
|
|
});
|
|
|
|
it('rounds half-hours correctly inside the hours bucket', () =>
|
|
{
|
|
// 4.5 hours -> rounds to 5
|
|
expect(FriendlyTime.format((4 * HOUR) + (30 * MINUTE))).toBe('friendlytime.hours|5');
|
|
});
|
|
|
|
it('threshold=1 lets the larger bucket win sooner', () =>
|
|
{
|
|
// With default threshold=3, 90s would stay in "seconds"; with threshold=1
|
|
// it crosses into "minutes" (90s > 1*60s).
|
|
expect(FriendlyTime.format(90, '', 1)).toBe('friendlytime.minutes|2');
|
|
});
|
|
|
|
it('key suffix is appended to the bucket key', () =>
|
|
{
|
|
// Useful for plurals / variants ('s' for singular fallback, etc.)
|
|
expect(FriendlyTime.format(5, '.foo')).toBe('friendlytime.seconds.foo|5');
|
|
expect(FriendlyTime.format(4 * HOUR, '.foo')).toBe('friendlytime.hours.foo|4');
|
|
});
|
|
});
|
|
|
|
describe('FriendlyTime.shortFormat', () =>
|
|
{
|
|
it('uses the .short variant of each bucket', () =>
|
|
{
|
|
expect(FriendlyTime.shortFormat(5)).toBe('friendlytime.seconds.short|5');
|
|
expect(FriendlyTime.shortFormat(4 * MINUTE)).toBe('friendlytime.minutes.short|4');
|
|
expect(FriendlyTime.shortFormat(4 * HOUR)).toBe('friendlytime.hours.short|4');
|
|
expect(FriendlyTime.shortFormat(5 * DAY)).toBe('friendlytime.days.short|5');
|
|
expect(FriendlyTime.shortFormat(4 * MONTH)).toBe('friendlytime.months.short|4');
|
|
expect(FriendlyTime.shortFormat(4 * YEAR)).toBe('friendlytime.years.short|4');
|
|
});
|
|
|
|
it('respects the optional key suffix and threshold', () =>
|
|
{
|
|
expect(FriendlyTime.shortFormat(2 * MINUTE, '.bar', 1)).toBe('friendlytime.minutes.short.bar|2');
|
|
});
|
|
});
|
|
|
|
describe('FriendlyTime.getLocalization', () =>
|
|
{
|
|
it('formats an arbitrary key and amount with the (amount, AMOUNT) replacements', () =>
|
|
{
|
|
expect(FriendlyTime.getLocalization('whatever', 42)).toBe('whatever|42');
|
|
});
|
|
});
|