diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 7ed659f7..b0ed31f7 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -110,7 +110,12 @@ const ALL_RETURNING_NODES = [ ...METHODS_RETURNING_NODES, ]; -const PRESENCE_MATCHERS = ['toBeInTheDocument', 'toBeTruthy', 'toBeDefined']; +const PRESENCE_MATCHERS = [ + 'toBeOnTheScreen', + 'toBeInTheDocument', + 'toBeTruthy', + 'toBeDefined', +]; const ABSENCE_MATCHERS = ['toBeNull', 'toBeFalsy']; export { diff --git a/tests/lib/rules/prefer-presence-queries.test.ts b/tests/lib/rules/prefer-presence-queries.test.ts index a5e8b3c9..488534c7 100644 --- a/tests/lib/rules/prefer-presence-queries.test.ts +++ b/tests/lib/rules/prefer-presence-queries.test.ts @@ -138,6 +138,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.toBeInTheDocument()', assertionType: 'presence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + assertionType: 'presence', + }), ...getValidAssertions({ query: queryName, matcher: '.toBeTruthy()', @@ -191,6 +196,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'presence', + }), ...getValidAssertions({ query: queryName, matcher: '.toBeTruthy()', @@ -251,6 +262,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.toBeInTheDocument()', assertionType: 'presence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + assertionType: 'presence', + }), ...getValidAssertions({ query: queryName, matcher: '.toBeTruthy()', @@ -304,6 +320,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'presence', + }), ...getValidAssertions({ query: queryName, matcher: '.toBeTruthy()', @@ -374,6 +396,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.not.toBeInTheDocument()', assertionType: 'absence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + assertionType: 'absence', + }), ...getValidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -419,6 +446,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'absence', + }), ...getValidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -465,6 +498,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.not.toBeInTheDocument()', assertionType: 'absence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + assertionType: 'absence', + }), ...getValidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -510,6 +548,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + ...getValidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'absence', + }), ...getValidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -557,6 +601,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.not.toBeInTheDocument', assertionType: 'absence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.not.toBeOnTheScreen', + assertionType: 'absence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeTruthy()', @@ -592,6 +641,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.not.toBeOnTheScreen', + shouldUseScreen: true, + assertionType: 'absence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeTruthy()', @@ -626,6 +681,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.not.toBeInTheDocument', assertionType: 'absence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.not.toBeOnTheScreen', + assertionType: 'absence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeTruthy()', @@ -661,6 +721,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.not.toBeOnTheScreen', + shouldUseScreen: true, + assertionType: 'absence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeTruthy()', @@ -695,6 +761,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.toBeInTheDocument()', assertionType: 'presence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.toBeOnTheScreen()', + assertionType: 'presence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeFalsy()', @@ -730,6 +801,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'presence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeFalsy()', @@ -764,6 +841,11 @@ ruleTester.run(RULE_NAME, rule, { matcher: '.toBeInTheDocument()', assertionType: 'presence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.toBeOnTheScreen()', + assertionType: 'presence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeFalsy()', @@ -799,6 +881,12 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + getDisabledValidAssertion({ + query: queryName, + matcher: '.toBeOnTheScreen()', + shouldUseScreen: true, + assertionType: 'presence', + }), getDisabledValidAssertion({ query: queryName, matcher: '.not.toBeFalsy()', @@ -867,6 +955,12 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'wrongAbsenceQuery', assertionType: 'absence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + messageId: 'wrongAbsenceQuery', + assertionType: 'absence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -907,6 +1001,13 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + messageId: 'wrongAbsenceQuery', + shouldUseScreen: true, + assertionType: 'absence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -946,6 +1047,12 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'wrongAbsenceQuery', assertionType: 'absence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + messageId: 'wrongAbsenceQuery', + assertionType: 'absence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -986,6 +1093,13 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'absence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.not.toBeOnTheScreen()', + messageId: 'wrongAbsenceQuery', + shouldUseScreen: true, + assertionType: 'absence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeTruthy()', @@ -1025,6 +1139,12 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'wrongPresenceQuery', assertionType: 'presence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + messageId: 'wrongPresenceQuery', + assertionType: 'presence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeFalsy()', @@ -1065,6 +1185,13 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + messageId: 'wrongPresenceQuery', + shouldUseScreen: true, + assertionType: 'presence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeFalsy()', @@ -1104,6 +1231,12 @@ ruleTester.run(RULE_NAME, rule, { messageId: 'wrongPresenceQuery', assertionType: 'presence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + messageId: 'wrongPresenceQuery', + assertionType: 'presence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeFalsy()', @@ -1144,6 +1277,13 @@ ruleTester.run(RULE_NAME, rule, { shouldUseScreen: true, assertionType: 'presence', }), + ...getInvalidAssertions({ + query: queryName, + matcher: '.toBeOnTheScreen()', + messageId: 'wrongPresenceQuery', + shouldUseScreen: true, + assertionType: 'presence', + }), ...getInvalidAssertions({ query: queryName, matcher: '.not.toBeFalsy()', @@ -1165,14 +1305,29 @@ ruleTester.run(RULE_NAME, rule, { code: 'expect(screen.getAllByText("button")[1]).not.toBeInTheDocument()', errors: [{ messageId: 'wrongAbsenceQuery', line: 1, column: 15 }], }, + { + code: 'expect(screen.getAllByText("button")[1]).not.toBeOnTheScreen()', + errors: [{ messageId: 'wrongAbsenceQuery', line: 1, column: 15 }], + }, { code: 'expect(screen.queryAllByText("button")[1]).toBeInTheDocument()', errors: [{ messageId: 'wrongPresenceQuery', line: 1, column: 15 }], }, + { + code: 'expect(screen.queryAllByText("button")[1]).toBeOnTheScreen()', + errors: [{ messageId: 'wrongPresenceQuery', line: 1, column: 15 }], + }, { code: ` // case: asserting presence incorrectly with custom queryBy* query expect(queryByCustomQuery("button")).toBeInTheDocument() + `, + errors: [{ messageId: 'wrongPresenceQuery', line: 3, column: 16 }], + }, + { + code: ` + // case: asserting presence incorrectly with custom queryBy* query + expect(queryByCustomQuery("button")).toBeOnTheScreen() `, errors: [{ messageId: 'wrongPresenceQuery', line: 3, column: 16 }], }, @@ -1180,6 +1335,13 @@ ruleTester.run(RULE_NAME, rule, { code: ` // case: asserting absence incorrectly with custom getBy* query expect(getByCustomQuery("button")).not.toBeInTheDocument() + `, + errors: [{ messageId: 'wrongAbsenceQuery', line: 3, column: 16 }], + }, + { + code: ` + // case: asserting absence incorrectly with custom getBy* query + expect(getByCustomQuery("button")).not.toBeOnTheScreen() `, errors: [{ messageId: 'wrongAbsenceQuery', line: 3, column: 16 }], }, @@ -1191,6 +1353,17 @@ ruleTester.run(RULE_NAME, rule, { // case: asserting presence incorrectly importing custom module import 'test-utils' expect(queryByRole("button")).toBeInTheDocument() + `, + errors: [{ line: 4, column: 14, messageId: 'wrongPresenceQuery' }], + }, + { + settings: { + 'testing-library/utils-module': 'test-utils', + }, + code: ` + // case: asserting presence incorrectly importing custom module + import 'test-utils' + expect(queryByRole("button")).toBeOnTheScreen() `, errors: [{ line: 4, column: 14, messageId: 'wrongPresenceQuery' }], }, @@ -1202,6 +1375,17 @@ ruleTester.run(RULE_NAME, rule, { // case: asserting absence incorrectly importing custom module import 'test-utils' expect(getByRole("button")).not.toBeInTheDocument() + `, + errors: [{ line: 4, column: 14, messageId: 'wrongAbsenceQuery' }], + }, + { + settings: { + 'testing-library/utils-module': 'test-utils', + }, + code: ` + // case: asserting absence incorrectly importing custom module + import 'test-utils' + expect(getByRole("button")).not.toBeOnTheScreen() `, errors: [{ line: 4, column: 14, messageId: 'wrongAbsenceQuery' }], }, @@ -1247,5 +1431,47 @@ ruleTester.run(RULE_NAME, rule, { { line: 3, column: 48, messageId: 'wrongPresenceQuery' }, ], }, + { + code: ` + // case: asserting within check does still work with improper outer clause + expect(within(screen.getByRole("button")).getByText("Hello")).not.toBeOnTheScreen()`, + errors: [{ line: 3, column: 46, messageId: 'wrongAbsenceQuery' }], + }, + { + code: ` + // case: asserting within check does still work with improper outer clause + expect(within(screen.getByRole("button")).queryByText("Hello")).toBeOnTheScreen()`, + errors: [{ line: 3, column: 46, messageId: 'wrongPresenceQuery' }], + }, + { + code: ` + // case: asserting within check does still work with improper outer clause and improper inner clause + expect(within(screen.queryByRole("button")).getByText("Hello")).not.toBeOnTheScreen()`, + errors: [ + { line: 3, column: 25, messageId: 'wrongPresenceQuery' }, + { line: 3, column: 48, messageId: 'wrongAbsenceQuery' }, + ], + }, + { + code: ` + // case: asserting within check does still work with proper outer clause and improper inner clause + expect(within(screen.queryByRole("button")).queryByText("Hello")).not.toBeOnTheScreen()`, + errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }], + }, + { + code: ` + // case: asserting within check does still work with proper outer clause and improper inner clause + expect(within(screen.queryByRole("button")).getByText("Hello")).toBeOnTheScreen()`, + errors: [{ line: 3, column: 25, messageId: 'wrongPresenceQuery' }], + }, + { + code: ` + // case: asserting within check does still work with improper outer clause and improper inner clause + expect(within(screen.queryByRole("button")).queryByText("Hello")).toBeOnTheScreen()`, + errors: [ + { line: 3, column: 25, messageId: 'wrongPresenceQuery' }, + { line: 3, column: 48, messageId: 'wrongPresenceQuery' }, + ], + }, ], });