mirror of
https://github.com/wahyd4/heygo.git
synced 2026-08-09 05:15:52 +10:00
feat: validate shortlink aliases
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { ALIAS_MAX_LENGTH, normalizeAlias, validateAlias } from '../worker/lib/aliases';
|
||||
|
||||
describe('alias normalization', () => {
|
||||
it('lowercases aliases', () => {
|
||||
expect(normalizeAlias('Claude')).toBe('claude');
|
||||
});
|
||||
|
||||
it('trims aliases', () => {
|
||||
expect(normalizeAlias(' claude ')).toBe('claude');
|
||||
});
|
||||
|
||||
it('keeps hyphen and underscore', () => {
|
||||
expect(normalizeAlias('my_link-1')).toBe('my_link-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('alias validation', () => {
|
||||
it('rejects empty string with exact error', () => {
|
||||
expect(validateAlias('')).toEqual({ ok: false, error: 'Alias is required' });
|
||||
expect(validateAlias(' ')).toEqual({ ok: false, error: 'Alias is required' });
|
||||
});
|
||||
|
||||
it('rejects path separators with exact error', () => {
|
||||
expect(validateAlias('a/b')).toEqual({
|
||||
ok: false,
|
||||
error: 'Alias may contain only letters, numbers, underscore, and hyphen',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects aliases starting with hyphen or underscore', () => {
|
||||
expect(validateAlias('-alias')).toEqual({
|
||||
ok: false,
|
||||
error: 'Alias may contain only letters, numbers, underscore, and hyphen',
|
||||
});
|
||||
expect(validateAlias('_alias')).toEqual({
|
||||
ok: false,
|
||||
error: 'Alias may contain only letters, numbers, underscore, and hyphen',
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts length 100 and rejects length 101', () => {
|
||||
const validAlias = 'a'.repeat(ALIAS_MAX_LENGTH);
|
||||
const tooLongAlias = 'a'.repeat(ALIAS_MAX_LENGTH + 1);
|
||||
|
||||
expect(validateAlias(validAlias)).toEqual({ ok: true, value: validAlias });
|
||||
expect(validateAlias(tooLongAlias)).toEqual({
|
||||
ok: false,
|
||||
error: 'Alias must be 100 characters or fewer',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
export const ALIAS_MAX_LENGTH = 100;
|
||||
|
||||
const ALIAS_INVALID_ERROR = 'Alias may contain only letters, numbers, underscore, and hyphen';
|
||||
const ALIAS_PATTERN = /^[a-z0-9][a-z0-9_-]{0,99}$/;
|
||||
|
||||
type AliasValidationSuccess = {
|
||||
ok: true;
|
||||
value: string;
|
||||
};
|
||||
|
||||
type AliasValidationFailure = {
|
||||
ok: false;
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type ValidationResult = AliasValidationSuccess | AliasValidationFailure;
|
||||
|
||||
export function normalizeAlias(input: string): string {
|
||||
return input.trim().replace(/[A-Z]/g, (character) => character.toLowerCase());
|
||||
}
|
||||
|
||||
export function validateAlias(input: string): ValidationResult {
|
||||
const value = normalizeAlias(input);
|
||||
|
||||
if (value.length === 0) {
|
||||
return { ok: false, error: 'Alias is required' };
|
||||
}
|
||||
|
||||
if (value.length > ALIAS_MAX_LENGTH) {
|
||||
return { ok: false, error: `Alias must be ${ALIAS_MAX_LENGTH} characters or fewer` };
|
||||
}
|
||||
|
||||
if (!ALIAS_PATTERN.test(value)) {
|
||||
return { ok: false, error: ALIAS_INVALID_ERROR };
|
||||
}
|
||||
|
||||
return { ok: true, value };
|
||||
}
|
||||
Reference in New Issue
Block a user