@yasanchezz/eslint-plugin-vue-data-testid
Version:
An `eslint` plugin for checking accessibility rules from within `.vue` files. Add `data-testid` to use better behavior testing
68 lines (67 loc) • 3.23 kB
JavaScript
import * as path from 'node:path';
import { calculateAttributeNames, getAttributeValue } from "../utils/index.js";
const fileAttributeNames = new Map();
export default function createRule({ attributeName = 'data-testid', }) {
return {
meta: {
docs: { description: 'data-testid attribute should be unique' },
type: 'suggestion',
fixable: 'code',
schema: [], // no options
},
create(context) {
const filename = path.basename(context.filename);
const extname = path.extname(context.filename);
if (extname !== '.vue') {
return {};
}
const attributeNames = fileAttributeNames.get(context.filename) ?? new Set();
fileAttributeNames.set(context.filename, attributeNames);
attributeNames.clear();
return context.sourceCode.parserServices.defineTemplateBodyVisitor({
VAttribute(node) {
const element = node.parent.parent;
const isRoot = element.parent.type === 'VDocumentFragment';
const name = node.key.type === 'VDirectiveKey'
? node.key.name.name
: node.key.name;
const value = node.value?.type === 'VLiteral'
? node.value.value
: undefined;
const attributes = Iterator.from(fileAttributeNames)
.reduce((result, [, set]) => result.union(set), new Set());
const option = {
nodeName: element.rawName,
filepath: context.filename,
filename,
isRoot,
classNames: Array.from(getAttributeValue(element, 'class'))
.flatMap(className => className.split(' '))
};
const userAttributeName = typeof attributeName === 'string'
? attributeName
: attributeName(option);
const searchedAttributeNames = calculateAttributeNames(userAttributeName);
if (searchedAttributeNames.has(name) && value && attributes.has(value)) {
const filename = Array.from(fileAttributeNames)
.filter(([, set]) => set.has(value))
.map(([filepath]) => path.basename(filepath))
.at(0);
context.report({
node: node,
message: `should make ${userAttributeName} unique. {{attribute}} has already defined in the file {{filename}}`,
data: {
attribute: value,
filename: filename ?? ''
}
});
}
if (searchedAttributeNames.has(name) && value) {
attributeNames.add(value);
}
return {};
}
});
}
};
}