From ef3e42ee3385a1067ef698a8ebfb68f1024cbae5 Mon Sep 17 00:00:00 2001 From: neon <18559658+neonsolstice@users.noreply.github.com> Date: Tue, 13 Oct 2026 19:25:52 +0000 Subject: [PATCH] fix(achievements): draw Epic Voyager's book-marked icon on the web The seed names the icon for Epic Voyager (long_book_3) book-marked, which lucide ships only as an alias of book-bookmark. The web's icon map had every other seeded name but not this one, so the badge drew the HelpCircle fallback. The map now has it, and a test reads the seed and fails if any seeded icon would fall back. --- .../__tests__/resolveLucideIcon.spec.ts | 15 +++++++++++++++ .../achievements/utils/resolveLucideIcon.ts | 3 +++ 2 files changed, 18 insertions(+) diff --git a/client/src/features/achievements/__tests__/resolveLucideIcon.spec.ts b/client/src/features/achievements/__tests__/resolveLucideIcon.spec.ts index 51117ec0a..e4ba0d715 100644 --- a/client/src/features/achievements/__tests__/resolveLucideIcon.spec.ts +++ b/client/src/features/achievements/__tests__/resolveLucideIcon.spec.ts @@ -1,8 +1,11 @@ +import { readFileSync } from 'node:fs' +import { resolve } from 'node:path' import { describe, it, expect } from 'vitest' import { resolveLucideIcon } from '../utils/resolveLucideIcon' import { ArrowLeftRight, BookHeart, + BookMarked, BookOpen, BookX, Flame, @@ -56,4 +59,16 @@ describe('resolveLucideIcon', () => { expect(resolveLucideIcon('orbit')).toBe(Orbit) expect(resolveLucideIcon('arrow-left-right')).toBe(ArrowLeftRight) }) + + it('resolves book-marked, which lucide ships only as an alias', () => { + expect(resolveLucideIcon('book-marked')).toBe(BookMarked) + }) + + it('resolves every icon the server seeds, so no achievement draws the fallback', () => { + const seed = readFileSync(resolve(process.cwd(), '../server/src/modules/achievement/seed/achievement-seed.ts'), 'utf8') + const names = [...new Set([...seed.matchAll(/iconName: '([^']+)'/g)].map((match) => match[1]!))] + + expect(names.length).toBeGreaterThan(0) + expect(names.filter((name) => resolveLucideIcon(name) === HelpCircle)).toEqual([]) + }) }) diff --git a/client/src/features/achievements/utils/resolveLucideIcon.ts b/client/src/features/achievements/utils/resolveLucideIcon.ts index bd56017b0..0d26ad202 100644 --- a/client/src/features/achievements/utils/resolveLucideIcon.ts +++ b/client/src/features/achievements/utils/resolveLucideIcon.ts @@ -4,6 +4,7 @@ import { ArrowUpDown, Award, BookHeart, + BookMarked, BookmarkCheck, BookOpen, BookX, @@ -64,6 +65,8 @@ const ICON_MAP: Record = { 'arrow-up-down': ArrowUpDown, award: Award, 'book-heart': BookHeart, + // Epic Voyager's seed name. Lucide ships it only as an alias of book-bookmark. + 'book-marked': BookMarked, 'bookmark-check': BookmarkCheck, 'book-open': BookOpen, 'book-x': BookX,