// Unit tests for the pure username policy (no DB): validation, reserved-name // blocklist, case normalization, SSO derivation + the dedup suffix loop. const { test } = require('node:test') const assert = require('node:assert/strict') const policy = require('../src/auth/usernamePolicy') test('validateUsername accepts a normal name and trims whitespace', () => { const r = policy.validateUsername(' Frodo_99 ') assert.equal(r.ok, true) assert.equal(r.name, 'Frodo_99') // trimmed, case preserved }) test('validateUsername rejects too-short / too-long / bad-charset names', () => { assert.equal(policy.validateUsername('ab').ok, false) // < 3 assert.equal(policy.validateUsername('x'.repeat(33)).ok, false) // > 32 assert.equal(policy.validateUsername('has space').ok, false) assert.equal(policy.validateUsername('emoji😀here').ok, false) }) test('reserved names are rejected case-insensitively', () => { for (const name of ['admin', 'ADMIN', 'Administrator', 'root', 'moderator', 'support', 'me']) { assert.equal(policy.isReserved(name), true, `${name} should be reserved`) assert.equal(policy.validateUsername(name).ok, false, `${name} should be rejected`) } assert.equal(policy.isReserved('frodo'), false) }) test('sanitizeToUsername strips disallowed chars and leading punctuation', () => { assert.equal(policy.sanitizeToUsername('Fró.do Baggins!'), 'Fro.doBaggins') assert.equal(policy.sanitizeToUsername('...weird'), 'weird') assert.equal(policy.sanitizeToUsername('a'.repeat(50)).length, policy.MAX_LEN) }) test('deriveUsernameBase prefers display name, then email local-part, then player', () => { assert.equal(policy.deriveUsernameBase({ name: 'Gandalf', email: 'g@x.com' }), 'Gandalf') assert.equal(policy.deriveUsernameBase({ name: '💥', email: 'samwise@shire.net' }), 'samwise') assert.equal(policy.deriveUsernameBase({ name: '', email: '' }), 'player') // A reserved derived base is skipped in favor of the next candidate. assert.equal(policy.deriveUsernameBase({ name: 'admin', email: 'realuser@x.com' }), 'realuser') }) test('candidateUsername yields the base then increasing suffixes, clamped to length', () => { assert.equal(policy.candidateUsername('bilbo', 0), 'bilbo') assert.equal(policy.candidateUsername('bilbo', 1), 'bilbo2') assert.equal(policy.candidateUsername('bilbo', 2), 'bilbo3') // Long base: the numeric suffix must survive the MAX_LEN clamp. const long = 'a'.repeat(policy.MAX_LEN) const c = policy.candidateUsername(long, 10) assert.ok(c.length <= policy.MAX_LEN) assert.ok(c.endsWith('11')) })