import path from 'node:path' import { beforeAll, describe, expect, it } from 'vitest' import { plainClassName } from '../oxlint-plugins/renderer-scrollbar-style.mjs' import { runOxlintPluginOnSources } from './oxlint-plugin-test-runner.mjs' const pluginPath = path.resolve('config/oxlint-plugins/renderer-scrollbar-style.mjs') function lintSources(sources) { return runOxlintPluginOnSources({ pluginName: 'renderer-scrollbar-style', pluginPath, sources, rules: { 'renderer-scrollbar-style/require-styled-vertical-scrollbar': 'warn' } }) } const violations = [ [ 'escaped class expression', String.raw`export const X = () =>
`, String.raw`'\x6fverflow-y-auto'` ], [ 'unstyled class', 'export const X = () => ', '"max-h-64 overflow-y-auto"' ], [ 'unstyled suffix-important class', 'export const X = () => ', '"max-h-64 overflow-y-auto!"' ], [ 'unknown scrollbar class', 'export const X = () => ', '"overflow-auto scrollbar-none"' ], [ 'separate class composer arguments', "export const X = () => ", "'overflow-y-auto'" ], [ 'conditional scrollbar', "export const X = ({ enabled }) => ", "'overflow-y-auto'" ], [ 'arbitrary class wrapper', "export const X = () => ", "'overflow-y-auto'" ], [ 'mismatched responsive variants', 'export const X = () => ', '"overflow-y-auto md:scrollbar-sleek"' ], [ 'inline overflow', "export const X = () => ", "overflowY: 'auto'" ], [ 'logical inline style spread', "export const X = ({ open }) => ", "overflowY: 'auto'" ], [ 'JSX spread class', "export const X = () => ", "'overflow-y-auto'" ], [ 'later spread override', 'export const X = () => ', "'overflow-y-auto'" ] ] const accepted = [ [ 'styled vertical class', 'export const X = () => ' ], [ 'styled suffix-important classes', 'export const X = () => ' ], [ 'same composer literal', "export const X = () => " ], [ 'same conditional literal', "export const X = ({ enabled }) => " ], ['horizontal-only overflow', 'export const X = () => '], [ 'matching responsive variants', 'export const X = () => ' ], [ 'unconditional scrollbar', 'export const X = () => ' ], [ 'styled inline overflow', 'export const X = () => ' ], [ 'styled JSX spread class', "export const X = () => " ], [ 'variant configuration', "export const X = () => " ] ] const diagnosticsBySource = new Map() beforeAll(() => { const sources = [...violations, ...accepted].map(([, source]) => source) lintSources(sources).forEach((diagnostics, index) => { diagnosticsBySource.set(sources[index], diagnostics) }) }) describe('renderer scrollbar style Oxlint plugin', () => { it.each(violations)('reports %s', (_name, source, reportedSource) => { const findings = diagnosticsBySource.get(source) expect(findings).toHaveLength(1) expect(findings[0].code).toBe('renderer-scrollbar-style(require-styled-vertical-scrollbar)') const { offset, length } = findings[0].labels[0].span expect( Buffer.from(source) .subarray(offset, offset + length) .toString('utf8') ).toBe(reportedSource) }) it.each(accepted)('accepts %s', (_name, source) => { expect(diagnosticsBySource.get(source)).toEqual([]) }) it.each([ ['md:overflow-y-auto', 'overflow-y-auto'], ['[&:hover]:overflow-y-auto', 'overflow-y-auto'], ['md:!scrollbar-editor', 'scrollbar-editor'], ['!scrollbar-editor', 'scrollbar-editor'], ['overflow-y-auto!', 'overflow-y-auto'], ['md:scrollbar-editor!', 'scrollbar-editor'] ])('normalizes %s', (token, expected) => { expect(plainClassName(token)).toBe(expected) }) })