Skip to content

Commit f5a983d

Browse files
authored
fix(to-have-text-content): improved handling non literals and regex in autofix (#65)
1 parent 808c623 commit f5a983d

File tree

2 files changed

+95
-10
lines changed

2 files changed

+95
-10
lines changed

src/__tests__/lib/rules/prefer-to-have-text-content.js

+64-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable no-template-curly-in-string */
12
/**
23
* @fileoverview Prefer toHaveTextContent over checking element.textContent
34
* @author Ben Monro
@@ -14,7 +15,7 @@ import * as rule from "../../../rules/prefer-to-have-text-content";
1415
// Tests
1516
//------------------------------------------------------------------------------
1617

17-
const ruleTester = new RuleTester();
18+
const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2015 } });
1819
ruleTester.run("prefer-to-have-text-content", rule, {
1920
valid: [
2021
`expect(string).toBe("foo")`,
@@ -93,6 +94,47 @@ ruleTester.run("prefer-to-have-text-content", rule, {
9394
],
9495
output: `expect(container.firstChild).toHaveTextContent(/foo/)`,
9596
},
97+
{
98+
code: `expect(container.textContent).toContain(FOO.bar)`,
99+
errors: [
100+
{
101+
message:
102+
"Use toHaveTextContent instead of asserting on DOM node attributes",
103+
},
104+
],
105+
output: `expect(container).toHaveTextContent(new RegExp(FOO.bar))`,
106+
},
107+
{
108+
code: `expect(container.textContent).not.toContain(FOO.bar)`,
109+
errors: [
110+
{
111+
message:
112+
"Use toHaveTextContent instead of asserting on DOM node attributes",
113+
},
114+
],
115+
output: `expect(container).not.toHaveTextContent(new RegExp(FOO.bar))`,
116+
},
117+
{
118+
code: "expect(container.textContent).toContain(`${FOO.bar} baz`)",
119+
errors: [
120+
{
121+
message:
122+
"Use toHaveTextContent instead of asserting on DOM node attributes",
123+
},
124+
],
125+
output:
126+
"expect(container).toHaveTextContent(new RegExp(`${FOO.bar} baz`))",
127+
},
128+
{
129+
code: `expect(container.textContent).toContain(bazify(FOO.bar))`,
130+
errors: [
131+
{
132+
message:
133+
"Use toHaveTextContent instead of asserting on DOM node attributes",
134+
},
135+
],
136+
output: `expect(container).toHaveTextContent(new RegExp(bazify(FOO.bar)))`,
137+
},
96138
{
97139
code: 'expect(element.textContent).toMatch("foo")',
98140
errors: [
@@ -103,6 +145,27 @@ ruleTester.run("prefer-to-have-text-content", rule, {
103145
],
104146
output: `expect(element).toHaveTextContent(/foo/)`,
105147
},
148+
{
149+
code: "expect(element.textContent).toMatch(/foo bar/)",
150+
errors: [
151+
{
152+
message:
153+
"Use toHaveTextContent instead of asserting on DOM node attributes",
154+
},
155+
],
156+
output: "expect(element).toHaveTextContent(/foo bar/)",
157+
},
158+
{
159+
code: "expect(element.textContent).not.toMatch(/foo bar/)",
160+
errors: [
161+
{
162+
message:
163+
"Use toHaveTextContent instead of asserting on DOM node attributes",
164+
},
165+
],
166+
output: "expect(element).not.toHaveTextContent(/foo bar/)",
167+
},
168+
106169
{
107170
code: 'expect(element.textContent).not.toMatch("foo")',
108171
errors: [

src/rules/prefer-to-have-text-content.js

+31-9
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,31 @@ export const create = (context) => ({
1616
node
1717
) {
1818
const expectedArg = node.parent.parent.parent.arguments[0];
19+
20+
const expectedArgSource = context.getSourceCode().getText(expectedArg);
1921
context.report({
2022
node: node.parent,
2123
message: `Use toHaveTextContent instead of asserting on DOM node attributes`,
22-
fix: (fixer) => [
23-
fixer.removeRange([node.property.range[0] - 1, node.property.range[1]]),
24-
fixer.replaceTextRange(
25-
node.parent.parent.property.range,
26-
"toHaveTextContent"
27-
),
28-
fixer.replaceTextRange(expectedArg.range, `/${expectedArg.value}/`),
29-
],
24+
fix: (fixer) => {
25+
return [
26+
fixer.removeRange([
27+
node.property.range[0] - 1,
28+
node.property.range[1],
29+
]),
30+
fixer.replaceTextRange(
31+
node.parent.parent.property.range,
32+
"toHaveTextContent"
33+
),
34+
fixer.replaceTextRange(
35+
expectedArg.range,
36+
expectedArg.type === "Literal"
37+
? expectedArg.regex
38+
? expectedArgSource
39+
: `/${expectedArg.value}/`
40+
: `new RegExp(${expectedArgSource})`
41+
),
42+
];
43+
},
3044
});
3145
},
3246
[`MemberExpression[property.name='textContent'][parent.callee.name='expect'][parent.parent.property.name=/toBe$|to(Strict)?Equal/]`](
@@ -63,6 +77,7 @@ export const create = (context) => ({
6377
node
6478
) {
6579
const expectedArg = node.parent.parent.parent.parent.arguments[0];
80+
const expectedArgSource = context.getSourceCode().getText(expectedArg);
6681
context.report({
6782
node: node.parent,
6883
message: `Use toHaveTextContent instead of asserting on DOM node attributes`,
@@ -72,7 +87,14 @@ export const create = (context) => ({
7287
node.parent.parent.parent.property.range,
7388
"toHaveTextContent"
7489
),
75-
fixer.replaceTextRange(expectedArg.range, `/${expectedArg.value}/`),
90+
fixer.replaceTextRange(
91+
expectedArg.range,
92+
expectedArg.type === "Literal"
93+
? expectedArg.regex
94+
? expectedArgSource
95+
: `/${expectedArg.value}/`
96+
: `new RegExp(${expectedArgSource})`
97+
),
7698
],
7799
});
78100
},

0 commit comments

Comments
 (0)