formatGeneratedNumber() passed the admin-supplied {SEQ:N} width straight
into String.padStart() with no upper bound. A careless or malicious
format value (e.g. {SEQ:999999999}) would try to allocate a
correspondingly huge string - on the backend that runs on every single
honey-batch/bottling creation once such a format is saved, and in the
newly added frontend preview it would run on every keystroke while
typing the format. Caps the effective width at 20 digits, far beyond
any realistic sequence number, in both the backend implementation and
its frontend port so they stay identical.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { formatGeneratedNumber } from './number-format';
|
|
|
|
describe('formatGeneratedNumber', () => {
|
|
// Constructed via local-time components (not an ISO string) so the test
|
|
// is deterministic regardless of the machine's timezone.
|
|
const date = new Date(2026, 2, 7);
|
|
|
|
it('substitutes year, month, day and a zero-padded sequence', () => {
|
|
const result = formatGeneratedNumber('WH-{YYYY}-{SEQ:4}', 7, date);
|
|
|
|
expect(result).toBe('WH-2026-0007');
|
|
});
|
|
|
|
it('supports {YY}, {MM}, {DD} and an unpadded {SEQ}', () => {
|
|
const result = formatGeneratedNumber('{YY}{MM}{DD}-{SEQ}', 3, date);
|
|
|
|
expect(result).toBe('260307-3');
|
|
});
|
|
|
|
it('does not truncate a sequence wider than the requested padding', () => {
|
|
const result = formatGeneratedNumber('L-{SEQ:2}', 12345, date);
|
|
|
|
expect(result).toBe('L-12345');
|
|
});
|
|
|
|
it('leaves a format with no placeholders unchanged', () => {
|
|
const result = formatGeneratedNumber('FIXED-NUMBER', 1, date);
|
|
|
|
expect(result).toBe('FIXED-NUMBER');
|
|
});
|
|
|
|
it('clamps a pathologically large {SEQ:N} width instead of allocating it', () => {
|
|
const result = formatGeneratedNumber('L-{SEQ:999999999}', 7, date);
|
|
|
|
expect(result).toBe(`L-${'0'.repeat(19)}7`);
|
|
expect(result.length).toBe(22);
|
|
});
|
|
});
|