-
Notifications
You must be signed in to change notification settings - Fork 2
feat(native): Add toHaveTextContent matcher #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/native-to-have-style
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,9 +2,9 @@ import { Assertion, AssertionError } from "@assertive-ts/core"; | |
| import { get } from "dot-prop-immutable"; | ||
| import { ReactTestInstance } from "react-test-renderer"; | ||
|
|
||
| import { instanceToString, isEmpty } from "./helpers/helpers"; | ||
| import { instanceToString, isEmpty, testableTextMatcherToString, textMatches } from "./helpers/helpers"; | ||
| import { getFlattenedStyle } from "./helpers/styles"; | ||
| import { AssertiveStyle } from "./helpers/types"; | ||
| import { AssertiveStyle, TestableTextMatcher, WithTextContent } from "./helpers/types"; | ||
|
|
||
| export class ElementAssertion extends Assertion<ReactTestInstance> { | ||
| public constructor(actual: ReactTestInstance) { | ||
|
|
@@ -243,6 +243,88 @@ export class ElementAssertion extends Assertion<ReactTestInstance> { | |
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Check if the element has text content matching the provided string, | ||
| * RegExp, or function. | ||
| * | ||
| * @example | ||
| * ``` | ||
| * expect(element).toHaveTextContent("Hello World"); | ||
| * expect(element).toHaveTextContent(/Hello/); | ||
| * expect(element).toHaveTextContent(text => text.startsWith("Hello")); | ||
| * ``` | ||
| * | ||
| * @param text - The text to check for. | ||
| * @returns the assertion instance | ||
| */ | ||
| public toHaveTextContent(text: TestableTextMatcher): this { | ||
| const actualTextContent = this.getTextContent(this.actual); | ||
| const matchesText = textMatches(actualTextContent, text); | ||
|
|
||
| const error = new AssertionError({ | ||
| actual: this.actual, | ||
| message: `Expected element ${this.toString()} to have text content matching '` + | ||
| `${testableTextMatcherToString(text)}'.`, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we use the |
||
| }); | ||
|
|
||
| const invertedError = new AssertionError({ | ||
| actual: this.actual, | ||
| message: | ||
| `Expected element ${this.toString()} NOT to have text content matching '` + | ||
| `${testableTextMatcherToString(text)}'.`, | ||
| }); | ||
|
|
||
| return this.execute({ | ||
| assertWhen: matchesText, | ||
| error, | ||
| invertedError, | ||
| }); | ||
| } | ||
|
|
||
| private getTextContent(element: ReactTestInstance): string { | ||
| if (!element) { | ||
| return ""; | ||
| } | ||
|
|
||
| if (typeof element === "string") { | ||
| return element; | ||
| } | ||
|
|
||
| if (typeof element.props?.value === "string") { | ||
| return element.props.value; | ||
| } | ||
|
|
||
| return this.collectText(element).join(" "); | ||
| } | ||
|
|
||
| private collectText = (element: WithTextContent): string[] => { | ||
| if (typeof element === "string") { | ||
| return [element]; | ||
| } | ||
|
|
||
| if (Array.isArray(element)) { | ||
| return element.flatMap(child => this.collectText(child)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we sure flatMap will always work here? is the |
||
| } | ||
|
|
||
| if (element && typeof element === "object" && "props" in element) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you add parenthesis to group logical validations for a better readability please |
||
| const value = element.props?.value as WithTextContent; | ||
| if (typeof value === "string") { | ||
| return [value]; | ||
| } | ||
|
|
||
| const children = (element.props?.children as ReactTestInstance[]) ?? element.children; | ||
| if (!children) { | ||
| return []; | ||
| } | ||
|
|
||
| return Array.isArray(children) | ||
| ? children.flatMap(this.collectText) | ||
| : this.collectText(children); | ||
| } | ||
|
|
||
| return []; | ||
| }; | ||
|
|
||
| private isElementDisabled(element: ReactTestInstance): boolean { | ||
| const { type } = element; | ||
| const elementType = type.toString(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import { ImageStyle, StyleProp, TextStyle, ViewStyle } from "react-native"; | ||
| import { ReactTestInstance } from "react-test-renderer"; | ||
|
|
||
| /** | ||
| * Type representing a style that can be applied to a React Native component. | ||
|
|
@@ -17,3 +18,17 @@ export type AssertiveStyle = StyleProp<Style>; | |
| * It is a record where the keys are strings and the values can be of any type. | ||
| */ | ||
| export type StyleObject = Record<string, unknown>; | ||
|
|
||
| /** | ||
| * Type representing a matcher for text in tests. | ||
| * | ||
| * It can be a string, a regular expression, or a function that | ||
| * takes a string and returns a boolean. | ||
| */ | ||
| export type TestableTextMatcher = string | RegExp | ((text: string) => boolean); | ||
|
|
||
| /** | ||
| * Type representing a value that can be used to match text content in tests. | ||
| * It can be a string, a ReactTestInstance, or an array of ReactTestInstances. | ||
| */ | ||
| export type WithTextContent = string | ReactTestInstance | ReactTestInstance[]; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. type naming for |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could validate that
textis a string, RegExp, or function before this line so we can throw the error fromhelpers/testableTextMatcherToStringhere: