Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion packages/dom/src/lib/ElementAssertion.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Assertion, AssertionError } from "@assertive-ts/core";
import equal from "fast-deep-equal";

import { getExpectedAndReceivedStyles } from "./helpers/helpers";
import { getExpectedAndReceivedStyles, isElementEmpty } from "./helpers/helpers";

export class ElementAssertion<T extends Element> extends Assertion<T> {

Expand Down Expand Up @@ -260,6 +260,38 @@ export class ElementAssertion<T extends Element> extends Assertion<T> {
});
}

/**
* Asserts that the element does not contain child nodes, excluding comments.
*
* @example
* ```
* expect(component).toBeEmpty();
* ```
*
* @returns the assertion instance.
*/

public toBeEmpty(): this {

const isEmpty = isElementEmpty(this.actual);

const error = new AssertionError({
actual: this.actual,
message: "Expected the element to be empty.",
});

const invertedError = new AssertionError({
actual: this.actual,
message: "Expected the element NOT to be empty.",
});

return this.execute({
assertWhen: isEmpty,
error,
invertedError,
});
}

/**
* Helper method to assert the presence or absence of class names.
*
Expand Down
13 changes: 10 additions & 3 deletions packages/dom/src/lib/helpers/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ interface StyleDeclaration extends Record<string, string> {
value: string;
}

const COMMENT_NODE_TYPE = 8;

function normalizeStyles(css: Partial<CSSStyleDeclaration>): StyleDeclaration {
const normalizer = document.createElement("div");
document.body.appendChild(normalizer);
Expand Down Expand Up @@ -49,8 +51,8 @@ function getReceivedStyle (props: string[], received: CSSStyleDeclaration): Styl
}, {} as StyleDeclaration);
}

export const getExpectedAndReceivedStyles =
(actual: Element, expected: Partial<CSSStyleDeclaration>): StyleDeclaration[] => {
export function getExpectedAndReceivedStyles
(actual: Element, expected: Partial<CSSStyleDeclaration>): StyleDeclaration[] {
if (!actual.ownerDocument.defaultView) {
throw new Error("The element is not attached to a document with a default view.");
}
Expand All @@ -72,4 +74,9 @@ export const getExpectedAndReceivedStyles =
expectedStyle,
elementProcessedStyle,
];
};
}

export function isElementEmpty (element: Element): boolean {
const nonCommentChildNodes = [...element.childNodes].filter(child => child.nodeType !== COMMENT_NODE_TYPE);
return nonCommentChildNodes.length === 0;
}
54 changes: 54 additions & 0 deletions packages/dom/test/unit/lib/ElementAssertion.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,58 @@ describe("[Unit] ElementAssertion.test.ts", () => {
});
});
});

describe(".toBeEmpty", () => {
context("when the element does not contain any child node", () => {
it("returns the assertion instance", () => {
const { getByTestId } = render(<div data-testid="test-div" />);
const divTest = getByTestId("test-div");
const test = new ElementAssertion(divTest);

expect(test.toBeEmpty()).toBeEqual(test);

expect(() => test.not.toBeEmpty())
.toThrowError(AssertionError)
.toHaveMessage("Expected the element NOT to be empty.");

});
});

context("when the element contains a comment node", () => {
it("returns the assertion instance", () => {
const { getByTestId } = render(<div data-testid="test-div" />);
const divTest = getByTestId("test-div");
const comment = document.createComment("test comment");
divTest.appendChild(comment);
const test = new ElementAssertion(divTest);

expect(test.toBeEmpty()).toBeEqual(test);

expect(() => test.not.toBeEmpty())
.toThrowError(AssertionError)
.toHaveMessage("Expected the element NOT to be empty.");

});
});

context("when the element contains a child node", () => {
it("throws an assertion error", () => {
const { getByTestId } = render(<div data-testid="test-div" />);
const divTest = getByTestId("test-div");

const emptyDiv = document.createElement("div");
divTest.appendChild(emptyDiv);

const test = new ElementAssertion(divTest);

expect(() => test.toBeEmpty())
.toThrowError(AssertionError)
.toHaveMessage("Expected the element to be empty.");

expect(test.not.toBeEmpty()).toBeEqual(test);

});
});
});

});