From f7871e38544119fa8477f3602f38d1b179dda97e Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Fri, 21 Mar 2025 17:11:32 -0500 Subject: [PATCH 01/16] Add toBeVisible matcher # Conflicts: # packages/native/src/lib/ElementAssertion.ts --- packages/native/src/lib/ElementAssertion.ts | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index f30d78b..a2258f2 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -121,6 +121,33 @@ export class ElementAssertion extends Assertion { }); } + /** + * Check if the element is visible. + * + * @example + * ``` + * expect(element).toBeVisible(); + * ``` + * + * @returns the assertion instance + */ + public toBeVisible(): this { + const error = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} to be visible.`, + }); + const invertedError = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} NOT to be visible.`, + }); + + return this.execute({ + assertWhen: this.isElementVisible(this.actual) && !this.isAncestorNotVisible(this.actual), + error, + invertedError, + }); + } + private isElementDisabled(element: ReactTestInstance): boolean { const { type } = element; const elementType = type.toString(); From b8c2020fbeb5bba2541d3df3236616524d2d2478 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Fri, 21 Mar 2025 17:14:51 -0500 Subject: [PATCH 02/16] Fix: Update JSDocs --- packages/native/src/lib/ElementAssertion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index a2258f2..e4a41c0 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -122,7 +122,7 @@ export class ElementAssertion extends Assertion { } /** - * Check if the element is visible. + * Check if the element is visible and has not been hidden by an ancestor. * * @example * ``` From 0ff3dab6b10d4289e539f619122cbe21992aa63a Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 17 Mar 2025 10:47:13 -0500 Subject: [PATCH 03/16] WIP: toBeEmpty function --- .../src/lib/ToBeEmptyElementAssertion.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 packages/native/src/lib/ToBeEmptyElementAssertion.ts diff --git a/packages/native/src/lib/ToBeEmptyElementAssertion.ts b/packages/native/src/lib/ToBeEmptyElementAssertion.ts new file mode 100644 index 0000000..3b59632 --- /dev/null +++ b/packages/native/src/lib/ToBeEmptyElementAssertion.ts @@ -0,0 +1,51 @@ +import { Assertion, AssertionError } from "@assertive-ts/core"; +import { ReactTestInstance } from "react-test-renderer"; + +export class ToBeEmptyElementAssertion extends Assertion { + public constructor(actual: ReactTestInstance) { + super(actual); + } + + public override toString = (): string => { + if (this.actual === null) { + return "null"; + } + + return `<${this.actual.type.toString()} ... />`; + }; + + /** + * Check if the element is empty. + * + * @example + * ``` + * expect(element).toBeEmptyElement(); + * ``` + * + * @returns the assertion instance + */ + public toBeEmptyElement(): this { + const error = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} to be empty.`, + }); + const invertedError = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} to NOT be empty.`, + }); + + return this.execute({ + assertWhen: this.isEmpty(this.actual), + error, + invertedError, + }); + } + + private isEmpty(element: ReactTestInstance): boolean { + if(!element?.props?.children) { + return true; + } + + return element?.props?.children.length === 0; + } +} \ No newline at end of file From 9655a2fb4ab39727c14db4b99ae3dd8edd2d862c Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 17 Mar 2025 10:47:33 -0500 Subject: [PATCH 04/16] toBeEmpty tests --- .../lib/ToBeEmptyElementAssertion.test.tsx | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx diff --git a/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx b/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx new file mode 100644 index 0000000..e28a680 --- /dev/null +++ b/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx @@ -0,0 +1,37 @@ +import { AssertionError, expect } from "@assertive-ts/core"; +import { render } from "@testing-library/react-native"; +import { View, Text } from "react-native"; + +import { ToBeEmptyElementAssertion } from "../../src/lib/ToBeEmptyElementAssertion"; + +describe("[Unit] ToBeEmptyElementAssertion.test.ts", () => { + describe(".toBeEmptyElement", () => { + context("when the element is empty", () => { + it("returns the assertion instance", () => { + const element = render(); + const test = new ToBeEmptyElementAssertion(element.getByTestId("id")); + + expect(test.toBeEmptyElement()).toBe(test); + expect(() => test.not.toBeEmptyElement()) + .toThrowError(AssertionError) + .toHaveMessage("Expected element to NOT be empty."); + }); + }); + + context("when the element is NOT empty", () => { + it("throws an error", () => { + const element = render( + + {"Not empty"} + , + ); + const test = new ToBeEmptyElementAssertion(element.getByTestId("id")); + + expect(test.not.toBeEmptyElement()).toBeEqual(test); + expect(() => test.toBeEmptyElement()) + .toThrowError(AssertionError) + .toHaveMessage("Expected element to be empty."); + }); + }); + }); +}); From bce26e23257926b5334f846a53a6cbbec42bebaa Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 17 Mar 2025 13:01:15 -0500 Subject: [PATCH 05/16] Fix: use element 'children' --- packages/native/src/lib/ToBeEmptyElementAssertion.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/native/src/lib/ToBeEmptyElementAssertion.ts b/packages/native/src/lib/ToBeEmptyElementAssertion.ts index 3b59632..ab0f2fd 100644 --- a/packages/native/src/lib/ToBeEmptyElementAssertion.ts +++ b/packages/native/src/lib/ToBeEmptyElementAssertion.ts @@ -42,10 +42,16 @@ export class ToBeEmptyElementAssertion extends Assertion { } private isEmpty(element: ReactTestInstance): boolean { - if(!element?.props?.children) { + const children = element?.children; + + if (!children) { return true; } - return element?.props?.children.length === 0; + if (Array.isArray(children)) { + return children.length === 0; + } + + return false; } -} \ No newline at end of file +} From 5d763e2621ed440590b0ceff309ff78fdc5fc2b7 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 17 Mar 2025 15:45:03 -0500 Subject: [PATCH 06/16] CR: Move isEmpty to a helper file --- .../src/lib/ToBeEmptyElementAssertion.ts | 21 ++++++------------- packages/native/src/lib/helpers/helpers.ts | 20 +++++++++++++++--- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/native/src/lib/ToBeEmptyElementAssertion.ts b/packages/native/src/lib/ToBeEmptyElementAssertion.ts index ab0f2fd..b6bede4 100644 --- a/packages/native/src/lib/ToBeEmptyElementAssertion.ts +++ b/packages/native/src/lib/ToBeEmptyElementAssertion.ts @@ -1,6 +1,11 @@ import { Assertion, AssertionError } from "@assertive-ts/core"; import { ReactTestInstance } from "react-test-renderer"; +import { isEmpty } from "./helpers/helpers"; + +/** + * Assertion for checking if a React element is empty. + */ export class ToBeEmptyElementAssertion extends Assertion { public constructor(actual: ReactTestInstance) { super(actual); @@ -35,23 +40,9 @@ export class ToBeEmptyElementAssertion extends Assertion { }); return this.execute({ - assertWhen: this.isEmpty(this.actual), + assertWhen: isEmpty(this.actual), error, invertedError, }); } - - private isEmpty(element: ReactTestInstance): boolean { - const children = element?.children; - - if (!children) { - return true; - } - - if (Array.isArray(children)) { - return children.length === 0; - } - - return false; - } } diff --git a/packages/native/src/lib/helpers/helpers.ts b/packages/native/src/lib/helpers/helpers.ts index 631395c..b3c8a46 100644 --- a/packages/native/src/lib/helpers/helpers.ts +++ b/packages/native/src/lib/helpers/helpers.ts @@ -7,9 +7,23 @@ import { ReactTestInstance } from "react-test-renderer"; * @returns A string representation of the instance. */ export function instanceToString(instance: ReactTestInstance | null): string { - if (instance === null) { - return "null"; + if (instance === null) { + return "null"; + } + + return `<${instance.type.toString()} ... />`; +} + +export function isEmpty(element: ReactTestInstance): boolean { + const children = element?.children; + + if (!children) { + return true; + } + + if (Array.isArray(children)) { + return children.length === 0; } - return `<${instance.type.toString()} ... />`; + return false; } From f75daf5f1521cabbfca05160d043436ea5f1c294 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 17 Mar 2025 15:55:33 -0500 Subject: [PATCH 07/16] Add isEmpty doc. --- .../native/src/lib/ToBeEmptyElementAssertion.ts | 2 +- packages/native/src/lib/helpers/helpers.ts | 16 ++++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/native/src/lib/ToBeEmptyElementAssertion.ts b/packages/native/src/lib/ToBeEmptyElementAssertion.ts index b6bede4..43d71b2 100644 --- a/packages/native/src/lib/ToBeEmptyElementAssertion.ts +++ b/packages/native/src/lib/ToBeEmptyElementAssertion.ts @@ -40,7 +40,7 @@ export class ToBeEmptyElementAssertion extends Assertion { }); return this.execute({ - assertWhen: isEmpty(this.actual), + assertWhen: isEmpty(this.actual.children), error, invertedError, }); diff --git a/packages/native/src/lib/helpers/helpers.ts b/packages/native/src/lib/helpers/helpers.ts index b3c8a46..9c371f4 100644 --- a/packages/native/src/lib/helpers/helpers.ts +++ b/packages/native/src/lib/helpers/helpers.ts @@ -14,15 +14,19 @@ export function instanceToString(instance: ReactTestInstance | null): string { return `<${instance.type.toString()} ... />`; } -export function isEmpty(element: ReactTestInstance): boolean { - const children = element?.children; - - if (!children) { +/** + * Checks if a value is empty. + * + * @param value - The value to check. + * @returns `true` if the value is empty, `false` otherwise. + */ +export function isEmpty(value: unknown): boolean { + if (!value) { return true; } - if (Array.isArray(children)) { - return children.length === 0; + if (Array.isArray(value)) { + return value.length === 0; } return false; From 5c7300bc97bd9eba62acad2c69a182378d9e1705 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Tue, 18 Mar 2025 13:01:54 -0500 Subject: [PATCH 08/16] Update: CR comments --- ...mentAssertion.ts => ToBeEmptyAssertion.ts} | 16 ++++------- packages/native/src/lib/helpers/helpers.ts | 28 +++++++++---------- .../lib/ToBeEmptyElementAssertion.test.tsx | 20 ++++++------- 3 files changed, 30 insertions(+), 34 deletions(-) rename packages/native/src/lib/{ToBeEmptyElementAssertion.ts => ToBeEmptyAssertion.ts} (67%) diff --git a/packages/native/src/lib/ToBeEmptyElementAssertion.ts b/packages/native/src/lib/ToBeEmptyAssertion.ts similarity index 67% rename from packages/native/src/lib/ToBeEmptyElementAssertion.ts rename to packages/native/src/lib/ToBeEmptyAssertion.ts index 43d71b2..b6bd603 100644 --- a/packages/native/src/lib/ToBeEmptyElementAssertion.ts +++ b/packages/native/src/lib/ToBeEmptyAssertion.ts @@ -1,22 +1,18 @@ import { Assertion, AssertionError } from "@assertive-ts/core"; import { ReactTestInstance } from "react-test-renderer"; -import { isEmpty } from "./helpers/helpers"; +import { instanceToString, isEmpty } from "./helpers/helpers"; /** * Assertion for checking if a React element is empty. */ -export class ToBeEmptyElementAssertion extends Assertion { +export class ToBeEmptyAssertion extends Assertion { public constructor(actual: ReactTestInstance) { super(actual); } public override toString = (): string => { - if (this.actual === null) { - return "null"; - } - - return `<${this.actual.type.toString()} ... />`; + return instanceToString(this.actual); }; /** @@ -24,19 +20,19 @@ export class ToBeEmptyElementAssertion extends Assertion { * * @example * ``` - * expect(element).toBeEmptyElement(); + * expect(element).toBeEmpty(); * ``` * * @returns the assertion instance */ - public toBeEmptyElement(): this { + public toBeEmpty(): this { const error = new AssertionError({ actual: this.actual, message: `Expected element ${this.toString()} to be empty.`, }); const invertedError = new AssertionError({ actual: this.actual, - message: `Expected element ${this.toString()} to NOT be empty.`, + message: `Expected element ${this.toString()} NOT to be empty.`, }); return this.execute({ diff --git a/packages/native/src/lib/helpers/helpers.ts b/packages/native/src/lib/helpers/helpers.ts index 9c371f4..6ab4db1 100644 --- a/packages/native/src/lib/helpers/helpers.ts +++ b/packages/native/src/lib/helpers/helpers.ts @@ -1,19 +1,5 @@ import { ReactTestInstance } from "react-test-renderer"; -/** - * Converts a ReactTestInstance to a string representation. - * - * @param instance The ReactTestInstance to convert. - * @returns A string representation of the instance. - */ -export function instanceToString(instance: ReactTestInstance | null): string { - if (instance === null) { - return "null"; - } - - return `<${instance.type.toString()} ... />`; -} - /** * Checks if a value is empty. * @@ -31,3 +17,17 @@ export function isEmpty(value: unknown): boolean { return false; } + +/** + * Converts a ReactTestInstance to a string representation. + * + * @param instance - The ReactTestInstance to convert. + * @returns A string representation of the instance. + */ +export function instanceToString(instance: ReactTestInstance | null): string { + if (instance === null) { + return "null"; + } + + return `<${instance.type.toString()} ... />`; +} diff --git a/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx b/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx index e28a680..86fcb21 100644 --- a/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx +++ b/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx @@ -2,19 +2,19 @@ import { AssertionError, expect } from "@assertive-ts/core"; import { render } from "@testing-library/react-native"; import { View, Text } from "react-native"; -import { ToBeEmptyElementAssertion } from "../../src/lib/ToBeEmptyElementAssertion"; +import { ToBeEmptyAssertion } from "../../src/lib/ToBeEmptyAssertion"; -describe("[Unit] ToBeEmptyElementAssertion.test.ts", () => { - describe(".toBeEmptyElement", () => { +describe("[Unit] toBeEmptyAssertion.test.ts", () => { + describe(".toBeEmpty", () => { context("when the element is empty", () => { it("returns the assertion instance", () => { const element = render(); - const test = new ToBeEmptyElementAssertion(element.getByTestId("id")); + const test = new ToBeEmptyAssertion(element.getByTestId("id")); - expect(test.toBeEmptyElement()).toBe(test); - expect(() => test.not.toBeEmptyElement()) + expect(test.toBeEmpty()).toBe(test); + expect(() => test.not.toBeEmpty()) .toThrowError(AssertionError) - .toHaveMessage("Expected element to NOT be empty."); + .toHaveMessage("Expected element NOT to be empty."); }); }); @@ -25,10 +25,10 @@ describe("[Unit] ToBeEmptyElementAssertion.test.ts", () => { {"Not empty"} , ); - const test = new ToBeEmptyElementAssertion(element.getByTestId("id")); + const test = new ToBeEmptyAssertion(element.getByTestId("id")); - expect(test.not.toBeEmptyElement()).toBeEqual(test); - expect(() => test.toBeEmptyElement()) + expect(test.not.toBeEmpty()).toBeEqual(test); + expect(() => test.toBeEmpty()) .toThrowError(AssertionError) .toHaveMessage("Expected element to be empty."); }); From d93e39c491f1ae93f1847c9e7163803d21fabfa1 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Thu, 20 Mar 2025 12:53:04 -0500 Subject: [PATCH 09/16] Move toBeEmptyAssertion to the element assertions --- packages/native/src/lib/ElementAssertion.ts | 2 +- packages/native/src/lib/ToBeEmptyAssertion.ts | 44 ------------------- .../lib/ToBeEmptyElementAssertion.test.tsx | 37 ---------------- 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 packages/native/src/lib/ToBeEmptyAssertion.ts delete mode 100644 packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index e4a41c0..ee46362 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -3,7 +3,7 @@ import { get } from "dot-prop-immutable"; import { Children } from "react"; import { ReactTestInstance } from "react-test-renderer"; -import { instanceToString } from "./helpers/helpers"; +import { instanceToString, isEmpty } from "./helpers/helpers"; export class ElementAssertion extends Assertion { public constructor(actual: ReactTestInstance) { diff --git a/packages/native/src/lib/ToBeEmptyAssertion.ts b/packages/native/src/lib/ToBeEmptyAssertion.ts deleted file mode 100644 index b6bd603..0000000 --- a/packages/native/src/lib/ToBeEmptyAssertion.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Assertion, AssertionError } from "@assertive-ts/core"; -import { ReactTestInstance } from "react-test-renderer"; - -import { instanceToString, isEmpty } from "./helpers/helpers"; - -/** - * Assertion for checking if a React element is empty. - */ -export class ToBeEmptyAssertion extends Assertion { - public constructor(actual: ReactTestInstance) { - super(actual); - } - - public override toString = (): string => { - return instanceToString(this.actual); - }; - - /** - * Check if the element is empty. - * - * @example - * ``` - * expect(element).toBeEmpty(); - * ``` - * - * @returns the assertion instance - */ - public toBeEmpty(): this { - const error = new AssertionError({ - actual: this.actual, - message: `Expected element ${this.toString()} to be empty.`, - }); - const invertedError = new AssertionError({ - actual: this.actual, - message: `Expected element ${this.toString()} NOT to be empty.`, - }); - - return this.execute({ - assertWhen: isEmpty(this.actual.children), - error, - invertedError, - }); - } -} diff --git a/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx b/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx deleted file mode 100644 index 86fcb21..0000000 --- a/packages/native/test/lib/ToBeEmptyElementAssertion.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { AssertionError, expect } from "@assertive-ts/core"; -import { render } from "@testing-library/react-native"; -import { View, Text } from "react-native"; - -import { ToBeEmptyAssertion } from "../../src/lib/ToBeEmptyAssertion"; - -describe("[Unit] toBeEmptyAssertion.test.ts", () => { - describe(".toBeEmpty", () => { - context("when the element is empty", () => { - it("returns the assertion instance", () => { - const element = render(); - const test = new ToBeEmptyAssertion(element.getByTestId("id")); - - expect(test.toBeEmpty()).toBe(test); - expect(() => test.not.toBeEmpty()) - .toThrowError(AssertionError) - .toHaveMessage("Expected element NOT to be empty."); - }); - }); - - context("when the element is NOT empty", () => { - it("throws an error", () => { - const element = render( - - {"Not empty"} - , - ); - const test = new ToBeEmptyAssertion(element.getByTestId("id")); - - expect(test.not.toBeEmpty()).toBeEqual(test); - expect(() => test.toBeEmpty()) - .toThrowError(AssertionError) - .toHaveMessage("Expected element to be empty."); - }); - }); - }); -}); From b8d00428e3dd590eafde54fa61712004c9684d22 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 24 Mar 2025 15:30:55 -0500 Subject: [PATCH 10/16] toContainElement() assertion --- packages/native/src/lib/ElementAssertion.ts | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index ee46362..df2f5b2 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -148,6 +148,50 @@ export class ElementAssertion extends Assertion { }); } + /** + * Check if an element is contained within another element. + * + * @example + * ``` + * expect(parent).toContainElement(child); + * ``` + * + * @param element - The element to check for. + * @returns the assertion instance + */ + public toContainElement(element: ReactTestInstance): this { + const error = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} to contain element ${instanceToString(element)}.`, + }); + const invertedError = new AssertionError({ + actual: this.actual, + message: `Expected element ${this.toString()} NOT to contain element ${instanceToString(element)}.`, + }); + + const isElementContained = ( + parentElement: ReactTestInstance, + childElement: ReactTestInstance, + ): boolean => { + if (parentElement === null || childElement === null) { + return false; + } + + return ( + parentElement.findAll( + node => + node.type === childElement.type && node.props === childElement.props, + ).length > 0 + ); + }; + + return this.execute({ + assertWhen: isElementContained(this.actual, element), + error, + invertedError, + }); + } + private isElementDisabled(element: ReactTestInstance): boolean { const { type } = element; const elementType = type.toString(); From 8328f489665b5eeb557ac28e82f72978ab5225a8 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 24 Mar 2025 15:36:10 -0500 Subject: [PATCH 11/16] Add tests for toContainElement() --- .../native/test/lib/ElementAssertion.test.tsx | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/packages/native/test/lib/ElementAssertion.test.tsx b/packages/native/test/lib/ElementAssertion.test.tsx index 575046d..f04b23c 100644 --- a/packages/native/test/lib/ElementAssertion.test.tsx +++ b/packages/native/test/lib/ElementAssertion.test.tsx @@ -311,4 +311,50 @@ describe("[Unit] ElementAssertion.test.ts", () => { }); }); }); + + describe (".toContainElement", () => { + const element = render( + + + + + + , + ); + + const container = element.getByTestId("grandParentId"); + const containerElementAssertion = new ElementAssertion(container); + const parent = element.getByTestId("parentId"); + const parentElementAssertion = new ElementAssertion(parent); + const child = element.getByTestId("childId"); + const text = element.getByTestId("textId"); + + context("when the container element contains the target element", () => { + it("returns the assertion instance", () => { + expect(containerElementAssertion.toContainElement(parent)).toBe(containerElementAssertion); + expect(containerElementAssertion.toContainElement(child)).toBe(containerElementAssertion); + expect(containerElementAssertion.toContainElement(text)).toBe(containerElementAssertion); + expect(parentElementAssertion.toContainElement(child)).toBe(parentElementAssertion); + }); + + it("returns the assertion instance for negated assertions when the target element is not contained", () => { + expect(parentElementAssertion.not.toContainElement(text)).toBe(parentElementAssertion); + expect(parentElementAssertion.not.toContainElement(container)).toBe(parentElementAssertion); + }); + }); + + context("when the container element does NOT contain the target element", () => { + it("throws an error", () => { + expect(() => containerElementAssertion.not.toContainElement(parent)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element NOT to contain element ."); + expect(() => containerElementAssertion.not.toContainElement(text)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element NOT to contain element ."); + expect(() => parentElementAssertion.toContainElement(text)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element to contain element ."); + }); + }); + }); }); From cbe8895c9d0971871141d97c52e932c50734a9fd Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Mon, 24 Mar 2025 15:49:32 -0500 Subject: [PATCH 12/16] fix: assertions on tests --- packages/native/test/lib/ElementAssertion.test.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/native/test/lib/ElementAssertion.test.tsx b/packages/native/test/lib/ElementAssertion.test.tsx index f04b23c..73c68bd 100644 --- a/packages/native/test/lib/ElementAssertion.test.tsx +++ b/packages/native/test/lib/ElementAssertion.test.tsx @@ -338,8 +338,8 @@ describe("[Unit] ElementAssertion.test.ts", () => { }); it("returns the assertion instance for negated assertions when the target element is not contained", () => { - expect(parentElementAssertion.not.toContainElement(text)).toBe(parentElementAssertion); - expect(parentElementAssertion.not.toContainElement(container)).toBe(parentElementAssertion); + expect(parentElementAssertion.not.toContainElement(text)).toBeEqual(parentElementAssertion); + expect(parentElementAssertion.not.toContainElement(container)).toBeEqual(parentElementAssertion); }); }); From 84baa6074bbb959101a5f03d9c12f90b63248d09 Mon Sep 17 00:00:00 2001 From: Karla Quistanchala Date: Tue, 22 Apr 2025 15:14:14 -0500 Subject: [PATCH 13/16] (CR): Address Code Review comments --- .../native/test/lib/ElementAssertion.test.tsx | 50 ++++++++++++------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/native/test/lib/ElementAssertion.test.tsx b/packages/native/test/lib/ElementAssertion.test.tsx index 73c68bd..155ec3b 100644 --- a/packages/native/test/lib/ElementAssertion.test.tsx +++ b/packages/native/test/lib/ElementAssertion.test.tsx @@ -328,32 +328,46 @@ describe("[Unit] ElementAssertion.test.ts", () => { const parentElementAssertion = new ElementAssertion(parent); const child = element.getByTestId("childId"); const text = element.getByTestId("textId"); + const textElementAssertion = new ElementAssertion(text); - context("when the container element contains the target element", () => { - it("returns the assertion instance", () => { - expect(containerElementAssertion.toContainElement(parent)).toBe(containerElementAssertion); - expect(containerElementAssertion.toContainElement(child)).toBe(containerElementAssertion); - expect(containerElementAssertion.toContainElement(text)).toBe(containerElementAssertion); - expect(parentElementAssertion.toContainElement(child)).toBe(parentElementAssertion); + context("when the element has children", () => { + context("and the target element is found in the children's element", () => { + it("returns the assertion instance", () => { + expect(containerElementAssertion.toContainElement(parent)).toBe(containerElementAssertion); + expect(containerElementAssertion.toContainElement(child)).toBe(containerElementAssertion); + expect(containerElementAssertion.toContainElement(text)).toBe(containerElementAssertion); + expect(parentElementAssertion.toContainElement(child)).toBe(parentElementAssertion); + }); + + it("throws an error for negative assertion", () => { + expect(() => containerElementAssertion.not.toContainElement(parent)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element NOT to contain element ."); + expect(() => containerElementAssertion.not.toContainElement(text)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element NOT to contain element ."); + }); }); - it("returns the assertion instance for negated assertions when the target element is not contained", () => { - expect(parentElementAssertion.not.toContainElement(text)).toBeEqual(parentElementAssertion); - expect(parentElementAssertion.not.toContainElement(container)).toBeEqual(parentElementAssertion); + context("and the target element is NOT found in the children's element", () => { + it("throws an error", () => { + expect(() => parentElementAssertion.toContainElement(text)) + .toThrowError(AssertionError) + .toHaveMessage("Expected element to contain element ."); + }); + + it("returns the assertion instance for negative assertion", () => { + expect(parentElementAssertion.not.toContainElement(text)).toBeEqual(parentElementAssertion); + expect(parentElementAssertion.not.toContainElement(container)).toBeEqual(parentElementAssertion); + }); }); }); - context("when the container element does NOT contain the target element", () => { + context("when the element does NOT have children", () => { it("throws an error", () => { - expect(() => containerElementAssertion.not.toContainElement(parent)) - .toThrowError(AssertionError) - .toHaveMessage("Expected element NOT to contain element ."); - expect(() => containerElementAssertion.not.toContainElement(text)) - .toThrowError(AssertionError) - .toHaveMessage("Expected element NOT to contain element ."); - expect(() => parentElementAssertion.toContainElement(text)) + expect(() => textElementAssertion.toContainElement(parent)) .toThrowError(AssertionError) - .toHaveMessage("Expected element to contain element ."); + .toHaveMessage("Expected element to contain element ."); }); }); }); From 795446d69a7a3c1fe311c134bea1f21f0833ad40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carolina=20Lo=CC=81pez?= Date: Mon, 14 Jul 2025 16:44:59 -0500 Subject: [PATCH 14/16] Do not use inner function --- packages/native/src/lib/ElementAssertion.ts | 31 ++++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index df2f5b2..4acb1ef 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -169,29 +169,26 @@ export class ElementAssertion extends Assertion { message: `Expected element ${this.toString()} NOT to contain element ${instanceToString(element)}.`, }); - const isElementContained = ( - parentElement: ReactTestInstance, - childElement: ReactTestInstance, - ): boolean => { - if (parentElement === null || childElement === null) { - return false; - } - - return ( - parentElement.findAll( - node => - node.type === childElement.type && node.props === childElement.props, - ).length > 0 - ); - }; - return this.execute({ - assertWhen: isElementContained(this.actual, element), + assertWhen: this.isElementContained(this.actual, element), error, invertedError, }); } + private isElementContained(parentElement: ReactTestInstance, childElement: ReactTestInstance): boolean { + if (parentElement === null || childElement === null) { + return false; + } + + return ( + parentElement.findAll( + node => + node.type === childElement.type && node.props === childElement.props, + ).length > 0 + ); + } + private isElementDisabled(element: ReactTestInstance): boolean { const { type } = element; const elementType = type.toString(); From a560a0594bff8a0d0f22f4941af7f569dc44e41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carolina=20Lo=CC=81pez?= Date: Mon, 14 Jul 2025 16:46:38 -0500 Subject: [PATCH 15/16] remove unused import --- packages/native/src/lib/ElementAssertion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index 4acb1ef..a782a64 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -3,7 +3,7 @@ import { get } from "dot-prop-immutable"; import { Children } from "react"; import { ReactTestInstance } from "react-test-renderer"; -import { instanceToString, isEmpty } from "./helpers/helpers"; +import { instanceToString } from "./helpers/helpers"; export class ElementAssertion extends Assertion { public constructor(actual: ReactTestInstance) { From b0c7b4d23093f1a3f8717f85a2316414e310f5ed Mon Sep 17 00:00:00 2001 From: Carolina Lopez Date: Tue, 22 Jul 2025 16:49:37 -0500 Subject: [PATCH 16/16] Remove duplicated function --- packages/native/src/lib/ElementAssertion.ts | 27 --------------------- 1 file changed, 27 deletions(-) diff --git a/packages/native/src/lib/ElementAssertion.ts b/packages/native/src/lib/ElementAssertion.ts index a782a64..bc804fc 100644 --- a/packages/native/src/lib/ElementAssertion.ts +++ b/packages/native/src/lib/ElementAssertion.ts @@ -121,33 +121,6 @@ export class ElementAssertion extends Assertion { }); } - /** - * Check if the element is visible and has not been hidden by an ancestor. - * - * @example - * ``` - * expect(element).toBeVisible(); - * ``` - * - * @returns the assertion instance - */ - public toBeVisible(): this { - const error = new AssertionError({ - actual: this.actual, - message: `Expected element ${this.toString()} to be visible.`, - }); - const invertedError = new AssertionError({ - actual: this.actual, - message: `Expected element ${this.toString()} NOT to be visible.`, - }); - - return this.execute({ - assertWhen: this.isElementVisible(this.actual) && !this.isAncestorNotVisible(this.actual), - error, - invertedError, - }); - } - /** * Check if an element is contained within another element. *