clone

an rts arena for scripts: submit tribe strategies over the web or mcp, run deterministic matches, watch them

main
tribes / worker / test / friendly-id.test.ts
friendly-id.test.ts 2.2K
1import { describe, expect, it } from 'vitest';2import { ADJECTIVES, NOUN_POOLS, friendlyId, isUniqueViolation } from '../src/friendly-id';34describe('friendly ids', () => {5 it('noun pools are pairwise disjoint (a bare name reveals its category)', () => {6 const kinds = ['user', 'script', 'sim'] as const;7 for (const a of kinds) {8 for (const b of kinds) {9 if (a === b) continue;10 const setB = new Set(NOUN_POOLS[b]);11 for (const noun of NOUN_POOLS[a]) {12 expect(setB.has(noun), `noun '${noun}' appears in both ${a} and ${b}`).toBe(false);13 }14 }15 }16 });1718 it('pools contain no duplicates and only url-safe lowercase words', () => {19 for (const list of [ADJECTIVES, ...Object.values(NOUN_POOLS)]) {20 expect(new Set(list).size).toBe(list.length);21 for (const w of list) expect(w).toMatch(/^[a-z]+(-[a-z]+)?$/);22 }23 });2425 it('is deterministic per (kind, seed, attempt) and varies across them', () => {26 expect(friendlyId('script', 'abc')).toBe(friendlyId('script', 'abc'));27 expect(friendlyId('script', 'abc')).not.toBe(friendlyId('sim', 'abc'));28 expect(friendlyId('script', 'abc', 0)).not.toBe(friendlyId('script', 'abc', 1));29 });3031 it('formats as adjective-noun, with a numeric tag on retries', () => {32 const base = friendlyId('sim', 'seed-x');33 const parts = base.split('-');34 expect(ADJECTIVES).toContain(parts[0]!);35 const retry = friendlyId('sim', 'seed-x', 3);36 expect(retry.split('-').length).toBeGreaterThanOrEqual(3); // second adjective, no number yet37 expect(/\d$/.test(retry)).toBe(false);38 const deep = friendlyId('sim', 'seed-x', 12);39 expect(deep.endsWith('-5')).toBe(true); // numeric tags only past the two-word tier40 });4142 it('uses nouns from the right pool', () => {43 for (let i = 0; i < 50; i++) {44 const name = friendlyId('user', `seed-${i}`);45 const noun = name.split('-').slice(1).join('-');46 expect(NOUN_POOLS.user).toContain(noun);47 }48 });4950 it('isUniqueViolation matches sqlite unique errors only', () => {51 expect(isUniqueViolation(new Error('UNIQUE constraint failed: users.id'))).toBe(true);52 expect(isUniqueViolation(new Error('no such table'))).toBe(false);53 expect(isUniqueViolation('nope')).toBe(false);54 });55});