Skip to content

Commit 7338362

Browse files
authored
feat(valid-expect): refactor valid-expect linting messages (#501)
1 parent 6570863 commit 7338362

File tree

2 files changed

+60
-67
lines changed

2 files changed

+60
-67
lines changed

src/rules/__tests__/valid-expect.test.ts

+21-21
Original file line numberDiff line numberDiff line change
@@ -99,25 +99,31 @@ ruleTester.run('valid-expect', rule, {
9999
*/
100100
{
101101
code: 'expect().toBe(true);',
102-
errors: [{ endColumn: 8, column: 7, messageId: 'noArgs' }],
102+
errors: [
103+
{ endColumn: 8, column: 7, messageId: 'incorrectNumberOfArguments' },
104+
],
103105
},
104106
{
105107
code: 'expect().toEqual("something");',
106-
errors: [{ endColumn: 8, column: 7, messageId: 'noArgs' }],
108+
errors: [
109+
{ endColumn: 8, column: 7, messageId: 'incorrectNumberOfArguments' },
110+
],
107111
},
108112
{
109113
code: 'expect("something", "else").toEqual("something");',
110-
errors: [{ endColumn: 26, column: 21, messageId: 'multipleArgs' }],
114+
errors: [
115+
{ endColumn: 26, column: 21, messageId: 'incorrectNumberOfArguments' },
116+
],
111117
},
112118
{
113119
code: 'expect("something");',
114-
errors: [{ endColumn: 20, column: 1, messageId: 'noAssertions' }],
120+
errors: [{ endColumn: 20, column: 1, messageId: 'matcherNotFound' }],
115121
},
116122
{
117123
code: 'expect();',
118124
errors: [
119-
{ endColumn: 9, column: 1, messageId: 'noAssertions' },
120-
{ endColumn: 8, column: 7, messageId: 'noArgs' },
125+
{ endColumn: 9, column: 1, messageId: 'matcherNotFound' },
126+
{ endColumn: 8, column: 7, messageId: 'incorrectNumberOfArguments' },
121127
],
122128
},
123129
{
@@ -126,8 +132,7 @@ ruleTester.run('valid-expect', rule, {
126132
{
127133
endColumn: 25,
128134
column: 14,
129-
messageId: 'matcherOnPropertyNotCalled',
130-
data: { propertyName: 'toBeDefined' },
135+
messageId: 'matcherNotCalled',
131136
},
132137
],
133138
},
@@ -137,8 +142,7 @@ ruleTester.run('valid-expect', rule, {
137142
{
138143
endColumn: 29,
139144
column: 18,
140-
messageId: 'matcherOnPropertyNotCalled',
141-
data: { propertyName: 'toBeDefined' },
145+
messageId: 'matcherNotCalled',
142146
},
143147
],
144148
},
@@ -148,8 +152,8 @@ ruleTester.run('valid-expect', rule, {
148152
{
149153
endColumn: 18,
150154
column: 14,
151-
messageId: 'invalidProperty',
152-
data: { propertyName: 'nope' },
155+
messageId: 'modifierUnknown',
156+
data: { modifierName: 'nope' },
153157
},
154158
],
155159
},
@@ -159,8 +163,7 @@ ruleTester.run('valid-expect', rule, {
159163
{
160164
endColumn: 22,
161165
column: 14,
162-
messageId: 'propertyWithoutMatcher',
163-
data: { propertyName: 'resolves' },
166+
messageId: 'matcherNotFound',
164167
},
165168
],
166169
},
@@ -170,8 +173,7 @@ ruleTester.run('valid-expect', rule, {
170173
{
171174
endColumn: 21,
172175
column: 14,
173-
messageId: 'propertyWithoutMatcher',
174-
data: { propertyName: 'rejects' },
176+
messageId: 'matcherNotFound',
175177
},
176178
],
177179
},
@@ -181,8 +183,7 @@ ruleTester.run('valid-expect', rule, {
181183
{
182184
endColumn: 17,
183185
column: 14,
184-
messageId: 'propertyWithoutMatcher',
185-
data: { propertyName: 'not' },
186+
messageId: 'matcherNotFound',
186187
},
187188
],
188189
},
@@ -538,8 +539,7 @@ ruleTester.run('valid-expect', rule, {
538539
{
539540
column: 37,
540541
endColumn: 41,
541-
messageId: 'matcherOnPropertyNotCalled',
542-
data: { propertyName: 'toBe' },
542+
messageId: 'matcherNotCalled',
543543
},
544544
],
545545
},
@@ -582,7 +582,7 @@ ruleTester.run('valid-expect', rule, {
582582
code: `test("valid-expect", async () => {
583583
await expect(Promise.resolve(1));
584584
});`,
585-
errors: [{ endColumn: 41, column: 15, messageId: 'noAssertions' }],
585+
errors: [{ endColumn: 41, column: 15, messageId: 'matcherNotFound' }],
586586
},
587587
],
588588
});

src/rules/valid-expect.ts

+39-46
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,10 @@ const promiseArrayExceptionKey = ({ start, end }: TSESTree.SourceLocation) =>
100100
`${start.line}:${start.column}-${end.line}:${end.column}`;
101101

102102
type MessageIds =
103-
| 'multipleArgs'
104-
| 'noArgs'
105-
| 'noAssertions'
106-
| 'invalidProperty'
107-
| 'propertyWithoutMatcher'
108-
| 'matcherOnPropertyNotCalled'
103+
| 'incorrectNumberOfArguments'
104+
| 'modifierUnknown'
105+
| 'matcherNotFound'
106+
| 'matcherNotCalled'
109107
| 'asyncMustBeAwaited'
110108
| 'promisesWithAsyncAssertionsMustBeAwaited';
111109

@@ -118,13 +116,10 @@ export default createRule<[{ alwaysAwait?: boolean }], MessageIds>({
118116
recommended: 'error',
119117
},
120118
messages: {
121-
multipleArgs: 'More than one argument was passed to expect().',
122-
noArgs: 'No arguments were passed to expect().',
123-
noAssertions: 'No assertion was called on expect().',
124-
invalidProperty:
125-
'"{{ propertyName }}" is not a valid property of expect.',
126-
propertyWithoutMatcher: '"{{ propertyName }}" needs to call a matcher.',
127-
matcherOnPropertyNotCalled: '"{{ propertyName }}" was not called.',
119+
incorrectNumberOfArguments: 'Expect takes one and only one argument.',
120+
modifierUnknown: 'Expect has no modifier named "{{ modifierName }}".',
121+
matcherNotFound: 'Expect must have a corresponding matcher call.',
122+
matcherNotCalled: 'Matchers must be called to assert.',
128123
asyncMustBeAwaited: 'Async assertions must be awaited{{ orReturned }}.',
129124
promisesWithAsyncAssertionsMustBeAwaited:
130125
'Promises which return async assertions must be awaited{{ orReturned }}.',
@@ -169,46 +164,45 @@ export default createRule<[{ alwaysAwait?: boolean }], MessageIds>({
169164

170165
const { expect, modifier, matcher } = parseExpectCall(node);
171166

172-
if (expect.arguments.length > 1) {
173-
const secondArgumentLocStart = expect.arguments[1].loc.start;
174-
const lastArgumentLocEnd =
175-
expect.arguments[node.arguments.length - 1].loc.end;
167+
if (expect.arguments.length !== 1) {
168+
const expectLength = getAccessorValue(expect.callee).length;
176169

177-
context.report({
178-
loc: {
179-
end: {
180-
column: lastArgumentLocEnd.column - 1,
181-
line: lastArgumentLocEnd.line,
182-
},
183-
start: secondArgumentLocStart,
170+
let loc: TSESTree.SourceLocation = {
171+
start: {
172+
column: node.loc.start.column + expectLength,
173+
line: node.loc.start.line,
184174
},
185-
messageId: 'multipleArgs',
186-
node,
187-
});
188-
} else if (expect.arguments.length === 0) {
189-
const expectLength = getAccessorValue(expect.callee).length;
190-
context.report({
191-
loc: {
175+
end: {
176+
column: node.loc.start.column + expectLength + 1,
177+
line: node.loc.start.line,
178+
},
179+
};
180+
181+
if (expect.arguments.length !== 0) {
182+
const { start } = expect.arguments[1].loc;
183+
const { end } = expect.arguments[node.arguments.length - 1].loc;
184+
185+
loc = {
186+
start,
192187
end: {
193-
column: node.loc.start.column + expectLength + 1,
194-
line: node.loc.start.line,
195-
},
196-
start: {
197-
column: node.loc.start.column + expectLength,
198-
line: node.loc.start.line,
188+
column: end.column - 1,
189+
line: end.line,
199190
},
200-
},
201-
messageId: 'noArgs',
191+
};
192+
}
193+
194+
context.report({
195+
messageId: 'incorrectNumberOfArguments',
202196
node,
197+
loc,
203198
});
204199
}
205200

206201
// something was called on `expect()`
207202
if (!matcher) {
208203
if (modifier) {
209204
context.report({
210-
data: { propertyName: modifier.name }, // todo: rename to 'modifierName'
211-
messageId: 'propertyWithoutMatcher', // todo: rename to 'modifierWithoutMatcher'
205+
messageId: 'matcherNotFound',
212206
node: modifier.node.property,
213207
});
214208
}
@@ -218,8 +212,8 @@ export default createRule<[{ alwaysAwait?: boolean }], MessageIds>({
218212

219213
if (matcher.node.parent && isExpectMember(matcher.node.parent)) {
220214
context.report({
221-
messageId: 'invalidProperty', // todo: rename to 'invalidModifier'
222-
data: { propertyName: matcher.name }, // todo: rename to 'matcherName' (or modifierName?)
215+
messageId: 'modifierUnknown',
216+
data: { modifierName: matcher.name },
223217
node: matcher.node.property,
224218
});
225219

@@ -228,8 +222,7 @@ export default createRule<[{ alwaysAwait?: boolean }], MessageIds>({
228222

229223
if (!matcher.arguments) {
230224
context.report({
231-
data: { propertyName: matcher.name }, // todo: rename to 'matcherName'
232-
messageId: 'matcherOnPropertyNotCalled', // todo: rename to 'matcherNotCalled'
225+
messageId: 'matcherNotCalled',
233226
node: matcher.node.property,
234227
});
235228
}
@@ -287,7 +280,7 @@ export default createRule<[{ alwaysAwait?: boolean }], MessageIds>({
287280
// nothing called on "expect()"
288281
'CallExpression:exit'(node: TSESTree.CallExpression) {
289282
if (isExpectCall(node) && isNoAssertionsParentNode(node.parent)) {
290-
context.report({ messageId: 'noAssertions', node });
283+
context.report({ messageId: 'matcherNotFound', node });
291284
}
292285
},
293286
};

0 commit comments

Comments
 (0)