/* eslint-env jest */ import fs from 'fs'; import path from 'path'; const SRC = path.resolve(__dirname, '../../..'); /** Every .tsx file under src, tests aside. */ const sources = (dir: string): string[] => fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => { const full = path.join(dir, entry.name); if (entry.isDirectory()) { return entry.name === '__tests__' ? [] : sources(full); } return full.endsWith('.tsx') ? [full] : []; }); it('renders every link-shaped Button as a link to Base UI', () => { // A Button drawn as or keeps button semantics unless told // otherwise: "disabled" lands on the anchor, where it means nothing to a // screen reader, and Base UI logs an error. const missing: string[] = []; for (const file of sources(SRC)) { const text = fs.readFileSync(file, 'utf8'); const buttons = text.matchAll( /]|<(?!\/?Button\b)[^>]*>)*?)>/gs ); for (const match of buttons) { const attributes = match[1]; if ( /render=\{\s*<(a|Link)\b/.test(attributes) && !attributes.includes('nativeButton') ) { const line = text.slice(0, match.index).split('\n').length; missing.push(`${path.relative(SRC, file)}:${line}`); } } } expect(missing).toEqual([]); });