mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 10:51:36 -04:00
ui: the two icon names that were only ever defaults (#652)
InfoPopup and HelpPopup default to `icon = 'info circle'` and `icon = 'help circle'`. Neither name was in iconNameAliases, so both fell through to the fallback glyph and logged an error -- and being defaults, they fired on every use of either helper. Opening Settings on a device logged 43 of them. The test that should have caught this was called "maps every icon name the app uses" and checked a list of twenty names written by hand; these two were not on it. It now reads the icon defaults off the source -- 85 of them -- and names the file it found an unmapped one in. Scanning `name='...'` as well was tried and reverted: `name` is overwhelmingly a form-field attribute, so it reported 27 field names as unmapped icons and failed on correct code. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7e63bbb3e2
commit
24e2dd8b9b
2 changed files with 38 additions and 7 deletions
|
|
@ -99,8 +99,10 @@ const iconNameAliases: Record<string, keyof typeof Tabler> = {
|
|||
'hdd': 'IconDeviceSdCard',
|
||||
'heart': 'IconHeart',
|
||||
'heartbeat': 'IconHeartRateMonitor',
|
||||
'help circle': 'IconHelpCircle',
|
||||
'history': 'IconHistory',
|
||||
'image': 'IconPhoto',
|
||||
'info circle': 'IconInfoCircle',
|
||||
'lightbulb': 'IconBulb',
|
||||
'lightbulb outline': 'IconBulb',
|
||||
'lightning': 'IconBolt',
|
||||
|
|
|
|||
|
|
@ -61,15 +61,44 @@ describe('Icon', () => {
|
|||
expect(container.querySelector('svg')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('maps every icon name the app uses', () => {
|
||||
// A name that falls through renders a fallback glyph, leaving a hole in the UI.
|
||||
const names = ['trash', 'warning sign', 'download', 'refresh', 'plus', 'edit', 'wifi',
|
||||
'search', 'lock', 'check', 'upload', 'play', 'folder', 'filter', 'file text',
|
||||
'external', 'disk', 'circle notched', 'terminal', 'eye'];
|
||||
it('maps every icon name the app defaults to', () => {
|
||||
/*
|
||||
* A name that falls through renders a fallback glyph, leaving a hole in the UI.
|
||||
*
|
||||
* Read off the source rather than listed by hand. The list this replaced held
|
||||
* twenty names and was titled "every icon name the app uses", and the two that
|
||||
* were actually missing -- `info circle` and `help circle`, the DEFAULTS of
|
||||
* InfoPopup and HelpPopup -- were not among them. Being defaults, they fired on
|
||||
* every use of those two helpers: opening Settings on a real device logged 43
|
||||
* console errors, which no test saw because the assertion only read its own list.
|
||||
*
|
||||
* Defaults only (`icon = '...'`). Scanning `name='...'` as well was tried and
|
||||
* reverted: `name` is overwhelmingly a form-field attribute, so it reported 27
|
||||
* field names as unmapped icons and would have failed on correct code.
|
||||
*/
|
||||
const SRC = path.join(__dirname, '..', '..');
|
||||
const sourceFiles = (dir) => fs.readdirSync(dir, {withFileTypes: true}).flatMap(entry => {
|
||||
const full = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) return entry.name === 'node_modules' ? [] : sourceFiles(full);
|
||||
if (!/\.(js|jsx|ts|tsx)$/.test(entry.name)) return [];
|
||||
if (/\.(test|cy)\.(js|jsx|ts|tsx)$/.test(entry.name)) return [];
|
||||
return [full];
|
||||
});
|
||||
|
||||
const unmapped = names.filter(name => !resolveIconName(name));
|
||||
const defaults = new Map();
|
||||
for (const file of sourceFiles(SRC)) {
|
||||
const source = fs.readFileSync(file, 'utf8');
|
||||
for (const match of source.matchAll(/\bicon(?:Name)?\s*=\s*(?:"([^"]+)"|'([^']+)')/g)) {
|
||||
const name = (match[1] ?? match[2]).toLowerCase().trim();
|
||||
if (!defaults.has(name)) defaults.set(name, path.relative(SRC, file));
|
||||
}
|
||||
}
|
||||
|
||||
expect(unmapped).toEqual([]);
|
||||
// The premise: a scan that matched nothing would report nothing unmapped.
|
||||
expect(defaults.size).toBeGreaterThan(50);
|
||||
|
||||
const unmapped = [...defaults].filter(([name]) => !resolveIconName(name));
|
||||
expect(unmapped.map(([name, file]) => `${name} (${file})`)).toEqual([]);
|
||||
});
|
||||
|
||||
it('hides decorative icons from assistive technology but names labelled ones', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue