Skip to content

Commit ea9b886

Browse files
committed
Only report errors for prefer-to-have-value on valid DTL queries
1 parent 5c8c9aa commit ea9b886

File tree

4 files changed

+314
-94
lines changed

4 files changed

+314
-94
lines changed

src/__tests__/lib/rules/prefer-to-have-value.js

Lines changed: 158 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,34 @@ import * as rule from "../../../rules/prefer-to-have-value";
1515
// Tests
1616
//------------------------------------------------------------------------------
1717

18-
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
18+
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2017 } });
1919

2020
const errors = [{ messageId: "use-to-have-value" }];
21-
ruleTester.run("prefer-empty", rule, {
21+
ruleTester.run("prefer-to-have-value", rule, {
2222
valid: [
2323
`expect(element).toHaveValue('foo')`,
2424
`expect(element.value).toBeGreaterThan(2);`,
2525
`expect(element.value).toBeLessThan(2);`,
26+
27+
`const element = document.getElementById('asdfasf');
28+
expect(element.value).toEqual('foo');`,
29+
30+
`let element;
31+
element = someOtherFunction();
32+
expect(element.value).toStrictEqual('foo');`,
33+
34+
`const element = { value: 'foo' };
35+
expect(element.value).toBe('foo');`,
36+
37+
`const element = document.getElementById('asdfasf');
38+
expect(element.value).not.toEqual('foo');`,
39+
40+
`let element;
41+
element = someOtherFunction();
42+
expect(element.value).not.toStrictEqual('foo');`,
43+
44+
`const element = { value: 'foo' };
45+
expect(element.value).not.toBe('foo');`,
2646
],
2747
invalid: [
2848
{
@@ -45,35 +65,159 @@ ruleTester.run("prefer-empty", rule, {
4565
errors,
4666
output: `expect(element).not.toHaveValue("foo")`,
4767
},
68+
//==========================================================================
4869
{
49-
code: `expect(element.value).toBe('foo')`,
70+
code: `expect(screen.getByRole("textbox").value).toEqual("foo")`,
5071
errors,
51-
output: `expect(element).toHaveValue('foo')`,
72+
output: `expect(screen.getByRole("textbox")).toHaveValue("foo")`,
5273
},
5374
{
54-
code: `expect(element.value).toEqual('foo')`,
75+
code: `expect(screen.queryByRole("dropdown").value).toEqual("foo")`,
5576
errors,
56-
output: `expect(element).toHaveValue('foo')`,
77+
output: `expect(screen.queryByRole("dropdown")).toHaveValue("foo")`,
5778
},
5879
{
59-
code: `expect(element.value).toStrictEqual('foo')`,
80+
code: `async function x() { expect((await screen.findByRole("textbox")).value).toEqual("foo") }`,
6081
errors,
61-
output: `expect(element).toHaveValue('foo')`,
82+
output: `async function x() { expect((await screen.findByRole("textbox"))).toHaveValue("foo") }`,
6283
},
6384
{
64-
code: `expect(element.value).not.toBe('foo')`,
85+
code: `const element = screen.getByRole("textbox"); expect(element.value).toBe("foo");`,
6586
errors,
66-
output: `expect(element).not.toHaveValue('foo')`,
87+
output: `const element = screen.getByRole("textbox"); expect(element).toHaveValue("foo");`,
6788
},
6889
{
69-
code: `expect(element.value).not.toEqual('foo')`,
90+
code: `expect(screen.getByRole("textbox").value).not.toEqual("foo")`,
7091
errors,
71-
output: `expect(element).not.toHaveValue('foo')`,
92+
output: `expect(screen.getByRole("textbox")).not.toHaveValue("foo")`,
7293
},
7394
{
74-
code: `expect(element.value).not.toStrictEqual('foo')`,
95+
code: `expect(screen.queryByRole("dropdown").value).not.toEqual("foo")`,
7596
errors,
76-
output: `expect(element).not.toHaveValue('foo')`,
97+
output: `expect(screen.queryByRole("dropdown")).not.toHaveValue("foo")`,
98+
},
99+
{
100+
code: `async function x() { expect((await screen.getByRole("textbox")).value).not.toEqual("foo") }`,
101+
errors,
102+
output: `async function x() { expect((await screen.getByRole("textbox"))).not.toHaveValue("foo") }`,
103+
},
104+
{
105+
code: `const element = screen.getByRole("textbox"); expect(element.value).not.toBe("foo");`,
106+
errors,
107+
output: `const element = screen.getByRole("textbox"); expect(element).not.toHaveValue("foo");`,
108+
},
109+
//==========================================================================
110+
{
111+
code: `expect(screen.getByTestId('bananas').value).toEqual('foo')`,
112+
errors: [
113+
{
114+
...errors[0],
115+
suggestions: [
116+
{
117+
desc: "Replace toEqual with toHaveValue",
118+
output: `expect(screen.getByTestId('bananas')).toHaveValue('foo')`,
119+
},
120+
],
121+
},
122+
],
123+
},
124+
{
125+
code: `expect(screen.queryByTestId('bananas').value).toBe('foo')`,
126+
errors: [
127+
{
128+
...errors[0],
129+
suggestions: [
130+
{
131+
desc: "Replace toBe with toHaveValue",
132+
output: `expect(screen.queryByTestId('bananas')).toHaveValue('foo')`,
133+
},
134+
],
135+
},
136+
],
137+
},
138+
{
139+
code: `async function x() { expect((await screen.findByTestId("bananas")).value).toStrictEqual("foo") }`,
140+
errors: [
141+
{
142+
...errors[0],
143+
suggestions: [
144+
{
145+
desc: "Replace toStrictEqual with toHaveValue",
146+
output: `async function x() { expect((await screen.findByTestId("bananas"))).toHaveValue("foo") }`,
147+
},
148+
],
149+
},
150+
],
151+
},
152+
{
153+
code: `let element; element = screen.getByTestId('bananas'); expect(element.value).toEqual('foo');`,
154+
errors: [
155+
{
156+
...errors[0],
157+
suggestions: [
158+
{
159+
desc: "Replace toEqual with toHaveValue",
160+
output: `let element; element = screen.getByTestId('bananas'); expect(element).toHaveValue('foo');`,
161+
},
162+
],
163+
},
164+
],
165+
},
166+
{
167+
code: `expect(screen.getByTestId('bananas').value).not.toEqual('foo')`,
168+
errors: [
169+
{
170+
...errors[0],
171+
suggestions: [
172+
{
173+
desc: "Replace toEqual with toHaveValue",
174+
output: `expect(screen.getByTestId('bananas')).not.toHaveValue('foo')`,
175+
},
176+
],
177+
},
178+
],
179+
},
180+
{
181+
code: `expect(screen.queryByTestId('bananas').value).not.toBe('foo')`,
182+
errors: [
183+
{
184+
...errors[0],
185+
suggestions: [
186+
{
187+
desc: "Replace toBe with toHaveValue",
188+
output: `expect(screen.queryByTestId('bananas')).not.toHaveValue('foo')`,
189+
},
190+
],
191+
},
192+
],
193+
},
194+
{
195+
code: `async function x() { expect((await screen.findByTestId("bananas")).value).not.toStrictEqual("foo") }`,
196+
errors: [
197+
{
198+
...errors[0],
199+
suggestions: [
200+
{
201+
desc: "Replace toStrictEqual with toHaveValue",
202+
output: `async function x() { expect((await screen.findByTestId("bananas"))).not.toHaveValue("foo") }`,
203+
},
204+
],
205+
},
206+
],
207+
},
208+
{
209+
code: `let element; element = screen.getByTestId('bananas'); expect(element.value).not.toEqual('foo');`,
210+
errors: [
211+
{
212+
...errors[0],
213+
suggestions: [
214+
{
215+
desc: "Replace toEqual with toHaveValue",
216+
output: `let element; element = screen.getByTestId('bananas'); expect(element).not.toHaveValue('foo');`,
217+
},
218+
],
219+
},
220+
],
77221
},
78222
],
79223
});

src/rules/prefer-in-document.js

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import { queries } from "../queries";
7+
import { getQueryNodeFromAssignment } from "../utils";
78

89
export const meta = {
910
type: "suggestion",
@@ -95,38 +96,6 @@ export const create = (context) => {
9596
});
9697
}
9798
}
98-
99-
function getQueryNodeFrom(expression) {
100-
return expression.type === "TSAsExpression"
101-
? getQueryNodeFrom(expression.expression)
102-
: expression.type === "AwaitExpression"
103-
? getQueryNodeFrom(expression.argument)
104-
: expression.callee;
105-
}
106-
107-
function getQueryNodeFromAssignment(identifierName) {
108-
const variable = context.getScope().set.get(identifierName);
109-
if (!variable) return;
110-
const init = variable.defs[0].node.init;
111-
112-
let queryNode;
113-
if (init) {
114-
// let foo = screen.<query>();
115-
queryNode = getQueryNodeFrom(init);
116-
} else {
117-
// let foo;
118-
// foo = screen.<query>();
119-
const assignmentRef = variable.references
120-
.reverse()
121-
.find((ref) => !!ref.writeExpr);
122-
if (!assignmentRef) {
123-
return;
124-
}
125-
const assignment = assignmentRef.writeExpr;
126-
queryNode = getQueryNodeFrom(assignment);
127-
}
128-
return queryNode;
129-
}
13099
return {
131100
// expect(<query>).not.<matcher>
132101
[`CallExpression[callee.object.object.callee.name='expect'][callee.object.property.name='not'][callee.property.name=${alternativeMatchers}], CallExpression[callee.object.callee.name='expect'][callee.object.property.name='not'][callee.object.arguments.0.argument.callee.name=${alternativeMatchers}]`](
@@ -151,7 +120,8 @@ export const create = (context) => {
151120
[`MemberExpression[object.object.callee.name=expect][object.property.name=not][property.name=${alternativeMatchers}][object.object.arguments.0.type=Identifier]`](
152121
node
153122
) {
154-
const queryNode = getQueryNodeFromAssignment(
123+
const queryExpression = getQueryNodeFromAssignment(
124+
context,
155125
node.object.object.arguments[0].name
156126
);
157127
const matcherNode = node.property;
@@ -162,7 +132,7 @@ export const create = (context) => {
162132

163133
check({
164134
negatedMatcher: true,
165-
queryNode,
135+
queryNode: queryExpression && queryExpression.callee,
166136
matcherNode,
167137
matcherArguments,
168138
expect,
@@ -172,7 +142,8 @@ export const create = (context) => {
172142
[`MemberExpression[object.callee.name=expect][property.name=${alternativeMatchers}][object.arguments.0.type=Identifier]`](
173143
node
174144
) {
175-
const queryNode = getQueryNodeFromAssignment(
145+
const queryExpression = getQueryNodeFromAssignment(
146+
context,
176147
node.object.arguments[0].name
177148
);
178149
const matcherNode = node.property;
@@ -181,7 +152,7 @@ export const create = (context) => {
181152

182153
check({
183154
negatedMatcher: false,
184-
queryNode,
155+
queryNode: queryExpression && queryExpression.callee,
185156
matcherNode,
186157
matcherArguments,
187158
});

0 commit comments

Comments
 (0)