diff --git a/packages/dom/src/lib/ElementAssertion.ts b/packages/dom/src/lib/ElementAssertion.ts index d72b8b9..5e90457 100644 --- a/packages/dom/src/lib/ElementAssertion.ts +++ b/packages/dom/src/lib/ElementAssertion.ts @@ -30,4 +30,42 @@ export class ElementAssertion extends Assertion { invertedError, }); } + + /** + * Check if the element has a specific attribute. + * + * @param name - The attribute name. + * @param expectedValue - The expected attribute value (Optional). + * @returns the assertion instance. + */ + public toHaveAttribute(name: string, expectedValue?: string): this { + const hasAttribute = this.actual.hasAttribute(name); + const receivedValue = this.actual.getAttribute(name); + const isExpectedValuePresent = expectedValue !== undefined; + + const error = new AssertionError({ + actual: receivedValue, + expected: expectedValue, + message: isExpectedValuePresent + ? `Expected to have attribute "${name}" with value "${expectedValue}", but received "${receivedValue}"` + : `Expected to have attribute "${name}"`, + }); + + const invertedError = new AssertionError({ + actual: receivedValue, + expected: expectedValue, + message: isExpectedValuePresent + ? `Expected to NOT have attribute "${name}" with value "${expectedValue}", but received "${receivedValue}"` + : `Expected to NOT have attribute "${name}"`, + }); + + return this.execute({ + assertWhen: (isExpectedValuePresent + ? hasAttribute && receivedValue === expectedValue + : hasAttribute), + error, + invertedError, + }); + } + } diff --git a/packages/dom/test/unit/lib/ElementAssertion.test.tsx b/packages/dom/test/unit/lib/ElementAssertion.test.tsx index 804bc53..b110348 100644 --- a/packages/dom/test/unit/lib/ElementAssertion.test.tsx +++ b/packages/dom/test/unit/lib/ElementAssertion.test.tsx @@ -12,6 +12,14 @@ function TestComponent(): ReactElement { ); } +function TestComponentElement(): ReactElement { + return ( + + ); +} + describe("[Unit] ElementAssertion.test.ts", () => { describe(".toBeInTheDocument", () => { context("when the element is in the document", () => { @@ -42,4 +50,63 @@ describe("[Unit] ElementAssertion.test.ts", () => { }); }); }); + + describe(".toHaveAttribute", () => { + context("when the element has the attribute with the expected value", () => { + it("returns the assertion instance", async () => { + const { findByRole } = render(); + const button = await findByRole("button", { name: "click me" }); + const test = new ElementAssertion(button); + + expect(test.toHaveAttribute("type", "submit")).toBeEqual(test); + + expect(() => test.not.toHaveAttribute("type", "submit")) + .toThrowError(AssertionError) + .toHaveMessage("Expected to NOT have attribute \"type\" with value \"submit\", but received \"submit\""); + }); + }); + + context("when the element has the attribute with a not expected value", () => { + it("throws an assertion error", async () => { + const { findByRole } = render(); + const button = await findByRole("button", { name: "click me" }); + const test = new ElementAssertion(button); + + expect(() => test.toHaveAttribute("type", "different value")) + .toThrowError(AssertionError) + .toHaveMessage("Expected to have attribute \"type\" with value \"different value\", but received \"submit\"", + ); + + expect(test.not.toHaveAttribute("type", "different value")).toBeEqual(test); + }); + }); + + context("when the element has the attribute without checking value", () => { + it("returns the assertion instance", async () => { + const { findByRole } = render(); + const button = await findByRole("button", { name: "click me" }); + const test = new ElementAssertion(button); + + expect(test.toHaveAttribute("disabled")).toBeEqual(test); + + expect(() => test.not.toHaveAttribute("disabled")) + .toThrowError(AssertionError) + .toHaveMessage("Expected to NOT have attribute \"disabled\""); + }); + }); + + context("when the element does not have the attribute", () => { + it("throws an assertion error", async () => { + const { findByRole } = render(); + const button = await findByRole("button", { name: "click me" }); + const test = new ElementAssertion(button); + + expect(() => test.toHaveAttribute("non-existent")) + .toThrowError(AssertionError) + .toHaveMessage("Expected to have attribute \"non-existent\""); + + expect(test.not.toHaveAttribute("non-existent")).toBeEqual(test); + }); + }); + }); });