Skip to content

Commit 56f459e

Browse files
committed
add unit tests
1 parent 155f82b commit 56f459e

6 files changed

+130
-39
lines changed

lib/rules/require-meta-docs-description.js

+7-10
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ module.exports = {
4545
return {
4646
Program() {
4747
const sourceCode = context.getSourceCode();
48+
const { scopeManager } = sourceCode;
4849
const info = utils.getRuleInfo(sourceCode);
4950

5051
if (info === null) {
@@ -57,17 +58,13 @@ module.exports = {
5758
: DEFAULT_PATTERN;
5859

5960
const metaNode = info.meta;
60-
const docsNode =
61-
metaNode &&
62-
metaNode.properties &&
63-
metaNode.properties.find(
64-
(p) => p.type === 'Property' && utils.getKeyName(p) === 'docs'
65-
);
61+
const docsNode = utils
62+
.evaluateObjectProperties(metaNode, scopeManager)
63+
.find((p) => p.type === 'Property' && utils.getKeyName(p) === 'docs');
6664

67-
const descriptionNode =
68-
docsNode &&
69-
docsNode.value.properties &&
70-
docsNode.value.properties.find(
65+
const descriptionNode = utils
66+
.evaluateObjectProperties(docsNode && docsNode.value, scopeManager)
67+
.find(
7168
(p) =>
7269
p.type === 'Property' && utils.getKeyName(p) === 'description'
7370
);

lib/rules/require-meta-docs-url.js

+12-13
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ module.exports = {
5050
*/
5151
create(context) {
5252
const options = context.options[0] || {};
53-
const sourceCode = context.getSourceCode();
5453
const filename = context.getFilename();
5554
const ruleName =
5655
filename === '<input>'
@@ -75,24 +74,24 @@ module.exports = {
7574

7675
return {
7776
Program() {
77+
const sourceCode = context.getSourceCode();
78+
const { scopeManager } = sourceCode;
79+
7880
const info = util.getRuleInfo(sourceCode);
7981
if (info === null) {
8082
return;
8183
}
8284

8385
const metaNode = info.meta;
84-
const docsPropNode =
85-
metaNode &&
86-
metaNode.properties &&
87-
metaNode.properties.find(
88-
(p) => p.type === 'Property' && util.getKeyName(p) === 'docs'
89-
);
90-
const urlPropNode =
91-
docsPropNode &&
92-
docsPropNode.value.properties &&
93-
docsPropNode.value.properties.find(
94-
(p) => p.type === 'Property' && util.getKeyName(p) === 'url'
95-
);
86+
const docsPropNode = util
87+
.evaluateObjectProperties(metaNode, scopeManager)
88+
.find((p) => p.type === 'Property' && util.getKeyName(p) === 'docs');
89+
const urlPropNode = util
90+
.evaluateObjectProperties(
91+
docsPropNode && docsPropNode.value,
92+
scopeManager
93+
)
94+
.find((p) => p.type === 'Property' && util.getKeyName(p) === 'url');
9695

9796
const staticValue = urlPropNode
9897
? getStaticValue(urlPropNode.value, context.getScope())

lib/utils.js

+11-15
Original file line numberDiff line numberDiff line change
@@ -747,23 +747,19 @@ module.exports = {
747747
* @returns {Node[]} the list of all properties that could be found
748748
*/
749749
evaluateObjectProperties(objectNode, scopeManager) {
750-
if (!objectNode) {
750+
if (!objectNode || objectNode.type !== 'ObjectExpression') {
751751
return [];
752752
}
753753

754-
const spreadElements = objectNode.properties.filter(
755-
(prop) => prop.type === 'SpreadElement'
756-
);
757-
const spreadElementNodes = spreadElements.map((spreadElement) =>
758-
findVariableValue(spreadElement.argument, scopeManager)
759-
);
760-
const spreadElementObjectNodes = spreadElementNodes.filter(
761-
(node) => node && node.type === 'ObjectExpression'
762-
);
763-
const spreadElementObjectNodeProperties = spreadElementObjectNodes.flatMap(
764-
(node) => node.properties
765-
);
766-
767-
return [...objectNode.properties, ...spreadElementObjectNodeProperties];
754+
return objectNode.properties.flatMap((property) => {
755+
if (property.type === 'SpreadElement') {
756+
const value = findVariableValue(property.argument, scopeManager);
757+
if (value && value.type === 'ObjectExpression') {
758+
return value.properties;
759+
}
760+
return [];
761+
}
762+
return [property];
763+
});
768764
},
769765
};

tests/lib/rules/require-meta-docs-description.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const RuleTester = require('eslint').RuleTester;
1111
// Tests
1212
// ------------------------------------------------------------------------------
1313

14-
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
14+
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 9 } });
1515
ruleTester.run('require-meta-docs-description', rule, {
1616
valid: [
1717
'foo()',
@@ -107,6 +107,15 @@ ruleTester.run('require-meta-docs-description', rule, {
107107
create(context) {}
108108
};
109109
`,
110+
// Spread.
111+
`
112+
const extraDocs = { description: 'enforce foo' };
113+
const extraMeta = { docs: { ...extraDocs } };
114+
module.exports = {
115+
meta: { ...extraMeta },
116+
create(context) {}
117+
};
118+
`,
110119
],
111120

112121
invalid: [

tests/lib/rules/require-meta-docs-url.js

+13
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,19 @@ tester.run('require-meta-docs-url', rule, {
155155
},
156156
],
157157
},
158+
{
159+
// Spread.
160+
filename: 'test-rule',
161+
code: `
162+
const extraDocs = { url: "path/to/test-rule.md" };
163+
const extraMeta = { docs: { ...extraDocs } };
164+
module.exports = {
165+
meta: { ...extraMeta },
166+
create() {}
167+
}
168+
`,
169+
options: [{ pattern: 'path/to/{{name}}.md' }],
170+
},
158171
],
159172

160173
invalid: [

tests/lib/utils.js

+77
Original file line numberDiff line numberDiff line change
@@ -1274,4 +1274,81 @@ describe('utils', () => {
12741274
});
12751275
});
12761276
});
1277+
1278+
describe('evaluateObjectProperties', function () {
1279+
it('behaves correctly with simple object expression', function () {
1280+
const ast = espree.parse('const obj = { a: 123, b: foo() };', {
1281+
ecmaVersion: 9,
1282+
range: true,
1283+
});
1284+
const scopeManager = eslintScope.analyze(ast);
1285+
const result = utils.evaluateObjectProperties(
1286+
ast.body[0].declarations[0].init,
1287+
scopeManager
1288+
);
1289+
assert.deepEqual(result, ast.body[0].declarations[0].init.properties);
1290+
});
1291+
1292+
it('behaves correctly with spreads of objects', function () {
1293+
const ast = espree.parse(
1294+
`
1295+
const extra1 = { a: 123 };
1296+
const extra2 = { b: 456 };
1297+
const obj = { ...extra1, c: 789, ...extra2 };
1298+
`,
1299+
{
1300+
ecmaVersion: 9,
1301+
range: true,
1302+
}
1303+
);
1304+
const scopeManager = eslintScope.analyze(ast);
1305+
const result = utils.evaluateObjectProperties(
1306+
ast.body[2].declarations[0].init,
1307+
scopeManager
1308+
);
1309+
assert.deepEqual(result, [
1310+
...ast.body[0].declarations[0].init.properties, // First spread properties
1311+
...ast.body[2].declarations[0].init.properties.filter(
1312+
(property) => property.type !== 'SpreadElement'
1313+
), // Non-spread properties
1314+
...ast.body[1].declarations[0].init.properties, // Second spread properties
1315+
]);
1316+
});
1317+
1318+
it('behaves correctly with non-variable spreads', function () {
1319+
const ast = espree.parse(`function foo() {} const obj = { ...foo() };`, {
1320+
ecmaVersion: 9,
1321+
range: true,
1322+
});
1323+
const scopeManager = eslintScope.analyze(ast);
1324+
const result = utils.evaluateObjectProperties(
1325+
ast.body[1].declarations[0].init,
1326+
scopeManager
1327+
);
1328+
assert.deepEqual(result, []);
1329+
});
1330+
1331+
it('behaves correctly with spread with variable that cannot be found', function () {
1332+
const ast = espree.parse(`const obj = { ...foo };`, {
1333+
ecmaVersion: 9,
1334+
range: true,
1335+
});
1336+
const scopeManager = eslintScope.analyze(ast);
1337+
const result = utils.evaluateObjectProperties(
1338+
ast.body[0].declarations[0].init,
1339+
scopeManager
1340+
);
1341+
assert.deepEqual(result, []);
1342+
});
1343+
1344+
it('behaves correctly when passed wrong node type', function () {
1345+
const ast = espree.parse(`foo();`, {
1346+
ecmaVersion: 9,
1347+
range: true,
1348+
});
1349+
const scopeManager = eslintScope.analyze(ast);
1350+
const result = utils.evaluateObjectProperties(ast.body[0], scopeManager);
1351+
assert.deepEqual(result, []);
1352+
});
1353+
});
12771354
});

0 commit comments

Comments
 (0)