Skip to content

Commit 902409d

Browse files
authored
Add files via upload
1 parent fd801fe commit 902409d

File tree

70 files changed

+8672
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+8672
-0
lines changed

__tests__/__util__/axeMapping.js

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/* eslint-disable import/prefer-default-export, no-underscore-dangle */
2+
import * as axe from 'axe-core';
3+
4+
export function axeFailMessage(checkId, data) {
5+
return axe.utils.getCheckMessage(checkId, 'fail', data);
6+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const defaultParserOptions = {
2+
ecmaVersion: 2018,
3+
ecmaFeatures: {
4+
experimentalObjectRestSpread: true,
5+
jsx: true,
6+
},
7+
};
8+
9+
export default function parserOptionsMapper({
10+
code,
11+
errors,
12+
options = [],
13+
parserOptions = {},
14+
settings,
15+
}) {
16+
return {
17+
code,
18+
errors,
19+
options,
20+
parserOptions: {
21+
...defaultParserOptions,
22+
...parserOptions,
23+
},
24+
settings,
25+
};
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @flow
3+
*/
4+
5+
import entries from 'object.entries';
6+
import flatMap from 'array.prototype.flatmap';
7+
import fromEntries from 'object.fromentries';
8+
9+
type ESLintTestRunnerTestCase = {
10+
code: string,
11+
errors: ?Array<{ message: string, type: string }>,
12+
options: ?Array<mixed>,
13+
parserOptions: ?Array<mixed>,
14+
settings?: {[string]: mixed},
15+
};
16+
17+
type RuleOptionsMapperFactoryType = (
18+
params: ESLintTestRunnerTestCase
19+
) => ESLintTestRunnerTestCase;
20+
21+
export default function ruleOptionsMapperFactory(ruleOptions: Array<mixed> = []): RuleOptionsMapperFactoryType {
22+
// eslint-disable-next-line
23+
return ({ code, errors, options, parserOptions, settings }: ESLintTestRunnerTestCase): ESLintTestRunnerTestCase => {
24+
return {
25+
code,
26+
errors,
27+
// Flatten the array of objects in an array of one object.
28+
options: [fromEntries(flatMap((options || []).concat(ruleOptions), (item) => entries(item)))],
29+
parserOptions,
30+
settings,
31+
};
32+
};
33+
}

__tests__/index-test.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* eslint global-require: 0 */
2+
3+
import fs from 'fs';
4+
import path from 'path';
5+
import expect from 'expect';
6+
import plugin from '../src';
7+
8+
const rules = fs.readdirSync(path.resolve(__dirname, '../src/rules/'))
9+
.map((f) => path.basename(f, '.js'));
10+
11+
describe('all rule files should be exported by the plugin', () => {
12+
rules.forEach((ruleName) => {
13+
it(`should export ${ruleName}`, () => {
14+
expect(plugin.rules[ruleName]).toEqual(
15+
require(path.join('../src/rules', ruleName)) // eslint-disable-line
16+
);
17+
});
18+
});
19+
});
20+
21+
describe('configurations', () => {
22+
it('should export a \'recommended\' configuration', () => {
23+
expect(plugin.configs.recommended).toBeDefined();
24+
});
25+
});
26+
27+
describe('schemas', () => {
28+
rules.forEach((ruleName) => {
29+
it(`${ruleName} should export a schema with type object`, () => {
30+
const rule = require(path.join('../src/rules', ruleName)); // eslint-disable-line
31+
const schema = rule.meta && rule.meta.schema && rule.meta.schema[0];
32+
const { type } = schema;
33+
34+
expect(type).toEqual('object');
35+
});
36+
});
37+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @fileoverview Enforce <marquee> elements are not used.
3+
* @author Ethan Cohen
4+
*/
5+
6+
// -----------------------------------------------------------------------------
7+
// Requirements
8+
// -----------------------------------------------------------------------------
9+
10+
import { RuleTester } from 'eslint';
11+
import parserOptionsMapper from '../../__util__/parserOptionsMapper';
12+
import rule from '../../../src/rules/accessible-emoji';
13+
14+
// -----------------------------------------------------------------------------
15+
// Tests
16+
// -----------------------------------------------------------------------------
17+
18+
const ruleTester = new RuleTester();
19+
20+
const expectedError = {
21+
message: 'Emojis should be wrapped in <span>, have role="img", and have an accessible description with aria-label or aria-labelledby.',
22+
type: 'JSXOpeningElement',
23+
};
24+
25+
ruleTester.run('accessible-emoji', rule, {
26+
valid: [
27+
{ code: '<div />;' },
28+
{ code: '<span />' },
29+
{ code: '<span>No emoji here!</span>' },
30+
{ code: '<span role="img" aria-label="Panda face">🐼</span>' },
31+
{ code: '<span role="img" aria-label="Snowman">&#9731;</span>' },
32+
{ code: '<span role="img" aria-labelledby="id1">🐼</span>' },
33+
{ code: '<span role="img" aria-labelledby="id1">&#9731;</span>' },
34+
{ code: '<span role="img" aria-labelledby="id1" aria-label="Snowman">&#9731;</span>' },
35+
{ code: '<span>{props.emoji}</span>' },
36+
{ code: '<span aria-hidden>{props.emoji}</span>' },
37+
{ code: '<span aria-hidden="true">🐼</span>' },
38+
{ code: '<span aria-hidden>🐼</span>' },
39+
{ code: '<div aria-hidden="true">🐼</div>' },
40+
{ code: '<input type="hidden">🐼</input>' },
41+
{
42+
code: '<CustomInput type="hidden">🐼</CustomInput>',
43+
settings: { 'jsx-a11y': { components: { CustomInput: 'input' } } },
44+
},
45+
].map(parserOptionsMapper),
46+
invalid: [
47+
{ code: '<span>🐼</span>', errors: [expectedError] },
48+
{ code: '<span>foo🐼bar</span>', errors: [expectedError] },
49+
{ code: '<span>foo 🐼 bar</span>', errors: [expectedError] },
50+
{ code: '<i role="img" aria-label="Panda face">🐼</i>', errors: [expectedError] },
51+
{ code: '<i role="img" aria-labelledby="id1">🐼</i>', errors: [expectedError] },
52+
{ code: '<Foo>🐼</Foo>', errors: [expectedError] },
53+
{ code: '<span aria-hidden="false">🐼</span>', errors: [expectedError] },
54+
{ code: '<CustomInput type="hidden">🐼</CustomInput>', errors: [expectedError] },
55+
].map(parserOptionsMapper),
56+
});

0 commit comments

Comments
 (0)