Skip to content

Commit

Permalink
feat(prefer-screen-queries): allow baseElement and container (#201)
Browse files Browse the repository at this point in the history
Closes #188
  • Loading branch information
gndelia authored Jul 29, 2020
1 parent 7b82eb9 commit b6fcc42
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 9 deletions.
5 changes: 5 additions & 0 deletions docs/rules/prefer-screen-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ const { rerender, unmount, asFragment } = render(<Foo />);
rerender(<Foo />);
asFragment();
unmount();

// using baseElement
const { getByText } = render(<Foo />, { baseElement: treeA });
// using container
const { getAllByText } = render(<Foo />, { container: treeA });
```

## Further Reading
Expand Down
6 changes: 5 additions & 1 deletion lib/node-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TSESTree } from '@typescript-eslint/experimental-utils';
import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';

export function isCallExpression(
node: TSESTree.Node
Expand Down Expand Up @@ -105,4 +105,8 @@ export function hasThenProperty(node: TSESTree.Node) {

export function isArrowFunctionExpression(node: TSESTree.Node): node is TSESTree.ArrowFunctionExpression {
return node && node.type === 'ArrowFunctionExpression'
}

export function isObjectExpression(node: TSESTree.Expression): node is TSESTree.ObjectExpression {
return node?.type === AST_NODE_TYPES.ObjectExpression
}
22 changes: 18 additions & 4 deletions lib/rules/prefer-screen-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,21 @@ import {
isCallExpression,
isProperty,
isIdentifier,
isObjectExpression,
} from '../node-utils';

export const RULE_NAME = 'prefer-screen-queries';
export type MessageIds = 'preferScreenQueries';
type Options = [];

const ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING = ['container', 'baseElement']
const ALL_QUERIES_COMBINATIONS_REGEXP = ALL_QUERIES_COMBINATIONS.join('|');

function usesContainerOrBaseElement(node: TSESTree.CallExpression) {
const secondArgument = node.arguments[1]
return isObjectExpression(secondArgument) && secondArgument.properties.some((property) => isProperty(property) && isIdentifier(property.key) && ALLOWED_RENDER_PROPERTIES_FOR_DESTRUCTURING.includes(property.key.name))
}

export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
name: RULE_NAME,
meta: {
Expand Down Expand Up @@ -50,9 +57,14 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({

return {
VariableDeclarator(node) {
const isWithinFunction = isCallExpression(node.init) && isIdentifier(node.init.callee) && node.init.callee.name === 'within';
if (!isCallExpression(node.init) || !isIdentifier(node.init.callee)) {
return
}
const isWithinFunction = node.init.callee.name === 'within';
// TODO add the custom render option #198
const usesRenderOptions = node.init.callee.name === 'render' && usesContainerOrBaseElement(node.init);

if (!isWithinFunction) {
if (!isWithinFunction && !usesRenderOptions) {
return
}

Expand Down Expand Up @@ -94,11 +106,13 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
isMemberExpression(node.parent) &&
isCallExpression(node.parent.object) &&
isIdentifier(node.parent.object.callee) &&
node.parent.object.callee.name !== 'within'
node.parent.object.callee.name !== 'within' &&
node.parent.object.callee.name === 'render' && !usesContainerOrBaseElement(node.parent.object)
) {
reportInvalidUsage(node);
return;
}

if (
isMemberExpression(node.parent) &&
isIdentifier(node.parent.object) &&
Expand All @@ -109,4 +123,4 @@ export default ESLintUtils.RuleCreator(getDocsUrl)<Options, MessageIds>({
},
};
},
});
});
77 changes: 73 additions & 4 deletions tests/lib/rules/prefer-screen-queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ const ruleTester = createRuleTester();

ruleTester.run(RULE_NAME, rule, {
valid: [
{
code: `const baz = () => 'foo'`
},
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `screen.${queryMethod}()`,
})),
Expand Down Expand Up @@ -80,12 +83,55 @@ ruleTester.run(RULE_NAME, rule, {
const utils = render(baz);
utils.unmount();
`
}
},
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod} } = render(baz, { baseElement: treeA })
expect(${queryMethod}(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod}: aliasMethod } = render(baz, { baseElement: treeA })
expect(aliasMethod(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod} } = render(baz, { container: treeA })
expect(${queryMethod}(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod}: aliasMethod } = render(baz, { container: treeA })
expect(aliasMethod(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod} } = render(baz, { baseElement: treeB, container: treeA })
expect(${queryMethod}(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
const { ${queryMethod}: aliasMethod } = render(baz, { baseElement: treeB, container: treeA })
expect(aliasMethod(baz)).toBeDefined()
`
})),
...ALL_QUERIES_COMBINATIONS.map((queryMethod: string) => ({
code: `
render(foo, { baseElement: treeA }).${queryMethod}()
`
}))
],

invalid: [
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `${queryMethod}()`,
code: `
const { ${queryMethod} } = render(foo)
${queryMethod}()`,
errors: [
{
messageId: 'preferScreenQueries',
Expand All @@ -95,7 +141,6 @@ ruleTester.run(RULE_NAME, rule, {
},
],
})),

...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `render().${queryMethod}()`,
errors: [
Expand All @@ -107,7 +152,17 @@ ruleTester.run(RULE_NAME, rule, {
},
],
})),

...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `render(foo, { hydrate: true }).${queryMethod}()`,
errors: [
{
messageId: 'preferScreenQueries',
data: {
name: queryMethod,
},
},
],
})),
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `component.${queryMethod}()`,
errors: [
Expand Down Expand Up @@ -161,6 +216,20 @@ ruleTester.run(RULE_NAME, rule, {
},
],
})),
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `
const { ${queryMethod} } = render(baz, { hydrate: true })
${queryMethod}(baz)
`,
errors: [
{
messageId: 'preferScreenQueries',
data: {
name: queryMethod,
},
},
],
})),
...ALL_QUERIES_COMBINATIONS.map(queryMethod => ({
code: `
const [myVariable] = within()
Expand Down

0 comments on commit b6fcc42

Please sign in to comment.