Skip to content

Commit

Permalink
feat(dom): DOM - toContainElement (#132)
Browse files Browse the repository at this point in the history
  • Loading branch information
matycarolina authored Aug 27, 2024
1 parent 975c8b2 commit 8d7ffba
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 23 deletions.
24 changes: 23 additions & 1 deletion packages/dom/src/lib/ElementAssertion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ export class ElementAssertion<T extends Element> extends Assertion<T> {
});
}

/**
* Check if a given container element contains a specified child element.
*
* @param element the child expected to be contained.
* @returns the assertion instance.
*/
public toContainElement(element: Element): this {
const error = new AssertionError({
actual: this.actual,
message: "Expected the container to contain the element",
});
const invertedError = new AssertionError({
actual: this.actual,
message: "Expected the container to NOT contain the element",
});

return this.execute({
assertWhen: this.actual.contains(element),
error,
invertedError,
});
}

/**
* Check if the element has a specific attribute.
*
Expand Down Expand Up @@ -67,5 +90,4 @@ export class ElementAssertion<T extends Element> extends Assertion<T> {
invertedError,
});
}

}
107 changes: 85 additions & 22 deletions packages/dom/test/unit/lib/ElementAssertion.test.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,17 @@
import { AssertionError, expect } from "@assertive-ts/core";
import { render } from "@testing-library/react";
import { ReactElement } from "react";

import { ElementAssertion } from "../../../src/lib/ElementAssertion";

function TestComponent(): ReactElement {
return (
<div>
<button>click me</button>
</div>
);
}

function TestComponentElement(): ReactElement {
return (
<button role="button" type="submit" className="btn primary" disabled>
click me
</button>
);
}
import { NestedElementsTestComponent } from "./fixtures/nestedElementsTestComponent";
import { SimpleTestComponent } from "./fixtures/simpleTestComponent";
import { WithAttributesTestComponent } from "./fixtures/withAttributesTestComponent";

describe("[Unit] ElementAssertion.test.ts", () => {
describe(".toBeInTheDocument", () => {
context("when the element is in the document", () => {
it("returns the assertion instance", async () => {
const { findByRole } = render(<TestComponent />);
const { findByRole } = render(<SimpleTestComponent />);
const button = await findByRole("button", { name: "click me" });
const test = new ElementAssertion(button);

Expand All @@ -39,7 +26,6 @@ describe("[Unit] ElementAssertion.test.ts", () => {
context("when the element is not in the document", () => {
it("throws an assertion error", () => {
const detachedElement = document.createElement("div");

const test = new ElementAssertion(detachedElement);

expect(() => test.toBeInTheDocument())
Expand All @@ -51,10 +37,87 @@ describe("[Unit] ElementAssertion.test.ts", () => {
});
});

describe(".toContainElement", () => {
context("when the descendant element is contained in the ancestor element", () => {
context("and it is a direct child", () => {
it("returns the assertion instance", async () => {
const { findByTestId } = render(<NestedElementsTestComponent />);
const grandparent = await findByTestId("grandparent");
const parent = await findByTestId("parent");
const child = await findByTestId("child");
const svgElement = await findByTestId("svg-element");
const grandparentTest = new ElementAssertion(grandparent);
const parentTest = new ElementAssertion(parent);

expect(grandparentTest.toContainElement(parent));
expect(grandparentTest.toContainElement(svgElement));
expect(parentTest.toContainElement(child));

expect(() => grandparentTest.not.toContainElement(parent))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to NOT contain the element");

expect(() => grandparentTest.not.toContainElement(svgElement))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to NOT contain the element");

expect(() => parentTest.not.toContainElement(child))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to NOT contain the element");
});
});

context("and it is an indirect child", () => {
it("returns the assertion instance", async () => {
const { findByTestId } = render(<NestedElementsTestComponent/>);
const grandparent = await findByTestId("grandparent");
const child = await findByTestId("child");
const grandparentTest = new ElementAssertion(grandparent);

expect(grandparentTest.toContainElement(child));

expect(() => grandparentTest.not.toContainElement(child))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to NOT contain the element");
});
});

context("and it is a deeply nested child", () => {
it("returns the assertion instance", async () => {
const { findByTestId } = render(<NestedElementsTestComponent/>);
const grandparent = await findByTestId("grandparent");
const deepChild = await findByTestId("deep-child");
const grandparentTest = new ElementAssertion(grandparent);

expect(grandparentTest.toContainElement(deepChild));

expect(() => grandparentTest.not.toContainElement(deepChild))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to NOT contain the element");
});
});
});

context("when element is NOT contained in ancestor element", () => {
it("throws an assertion error", async () => {
const notChildElement = document.createElement("span");
const { findByTestId } = render(<NestedElementsTestComponent/>);
const grandparent = await findByTestId("grandparent");
const grandparentTest = new ElementAssertion(grandparent);

expect(() => grandparentTest.toContainElement(notChildElement))
.toThrowError(AssertionError)
.toHaveMessage("Expected the container to contain the element");

expect(grandparentTest.not.toContainElement(notChildElement)).toBeEqual(grandparentTest);
});
});
});

describe(".toHaveAttribute", () => {
context("when the element has the attribute with the expected value", () => {
it("returns the assertion instance", async () => {
const { findByRole } = render(<TestComponentElement />);
const { findByRole } = render(<WithAttributesTestComponent />);
const button = await findByRole("button", { name: "click me" });
const test = new ElementAssertion(button);

Expand All @@ -68,7 +131,7 @@ describe("[Unit] ElementAssertion.test.ts", () => {

context("when the element has the attribute with a not expected value", () => {
it("throws an assertion error", async () => {
const { findByRole } = render(<TestComponentElement />);
const { findByRole } = render(<WithAttributesTestComponent />);
const button = await findByRole("button", { name: "click me" });
const test = new ElementAssertion(button);

Expand All @@ -83,7 +146,7 @@ describe("[Unit] ElementAssertion.test.ts", () => {

context("when the element has the attribute without checking value", () => {
it("returns the assertion instance", async () => {
const { findByRole } = render(<TestComponentElement />);
const { findByRole } = render(<WithAttributesTestComponent />);
const button = await findByRole("button", { name: "click me" });
const test = new ElementAssertion(button);

Expand All @@ -97,7 +160,7 @@ describe("[Unit] ElementAssertion.test.ts", () => {

context("when the element does not have the attribute", () => {
it("throws an assertion error", async () => {
const { findByRole } = render(<TestComponentElement />);
const { findByRole } = render(<WithAttributesTestComponent />);
const button = await findByRole("button", { name: "click me" });
const test = new ElementAssertion(button);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ReactElement } from "react";

export function NestedElementsTestComponent(): ReactElement {
return (
<span data-testid="grandparent">
<span data-testid="parent">
<span data-testid="child">
<span>
<span>
<span>
<span data-testid="deep-child"></span>
</span>
</span>
</span>
</span>
</span>
<svg data-testid="svg-element"></svg>
</span>
);
}
9 changes: 9 additions & 0 deletions packages/dom/test/unit/lib/fixtures/simpleTestComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ReactElement } from "react";

export function SimpleTestComponent(): ReactElement {
return (
<div>
<button>click me</button>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ReactElement } from "react";

export function WithAttributesTestComponent(): ReactElement {
return (
<button role="button" type="submit" className="btn primary" disabled={true}>
click me
</button>
);
}

0 comments on commit 8d7ffba

Please sign in to comment.