Skip to content

Commit da792b3

Browse files
fonsihersuany0805
andauthored
feat(dom): DOM - toHaveFocus (#151)
Co-authored-by: Suany Chalan <79164262+suany0805@users.noreply.github.com>
1 parent 6a50023 commit da792b3

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

packages/dom/src/lib/ElementAssertion.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,40 @@ export class ElementAssertion<T extends Element> extends Assertion<T> {
142142
);
143143
}
144144

145+
/**
146+
* Check if the provided element is currently focused in the document.
147+
*
148+
* @example
149+
* const userNameInput = document.querySelector('#username');
150+
* userNameInput.focus();
151+
* expect(userNameInput).toHaveFocus(); // passes
152+
* expect(userNameInput).not.toHaveFocus(); // fails
153+
*
154+
* @returns The assertion instance.
155+
*/
156+
public toHaveFocus(): this {
157+
158+
const hasFocus = this.actual === document.activeElement;
159+
160+
const error = new AssertionError({
161+
actual: this.actual,
162+
expected: document.activeElement,
163+
message: "Expected the element to be focused",
164+
});
165+
166+
const invertedError = new AssertionError({
167+
actual: this.actual,
168+
expected: document.activeElement,
169+
message: "Expected the element NOT to be focused",
170+
});
171+
172+
return this.execute({
173+
assertWhen: hasFocus,
174+
error,
175+
invertedError,
176+
});
177+
}
178+
145179
private getClassList(): string[] {
146180
return this.actual.className.split(/\s+/).filter(Boolean);
147181
}

packages/dom/test/unit/lib/ElementAssertion.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { render } from "@testing-library/react";
33

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

6+
import { FocusTestComponent } from "./fixtures/focusTestComponent";
67
import { HaveClassTestComponent } from "./fixtures/haveClassTestComponent";
78
import { NestedElementsTestComponent } from "./fixtures/nestedElementsTestComponent";
89
import { SimpleTestComponent } from "./fixtures/simpleTestComponent";
@@ -265,4 +266,34 @@ describe("[Unit] ElementAssertion.test.ts", () => {
265266
});
266267
});
267268

269+
describe(".toHaveFocus", () => {
270+
context("when the element has focus", () => {
271+
it("returns the assertion instance", () => {
272+
const { getByTestId } = render(<FocusTestComponent />);
273+
const input1 = getByTestId("input1");
274+
input1.focus();
275+
const test = new ElementAssertion(input1);
276+
277+
expect(test.toHaveFocus()).toBeEqual(test);
278+
279+
expect(() => test.not.toHaveFocus())
280+
.toThrowError(AssertionError)
281+
.toHaveMessage("Expected the element NOT to be focused");
282+
});
283+
});
284+
285+
context("when the element does not have focus", () => {
286+
it("throws an assertion error", () => {
287+
const { getByTestId } = render(<FocusTestComponent />);
288+
const input1 = getByTestId("input1");
289+
const test = new ElementAssertion(input1);
290+
291+
expect(() => test.toHaveFocus())
292+
.toThrowError(AssertionError)
293+
.toHaveMessage("Expected the element to be focused");
294+
295+
expect(test.not.toHaveFocus()).toBeEqual(test);
296+
});
297+
});
298+
});
268299
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { ReactElement } from "react";
2+
3+
export function FocusTestComponent(): ReactElement {
4+
return (
5+
<div>
6+
<input data-testid="input1" />
7+
<input data-testid="input2" />
8+
</div>
9+
);
10+
}

0 commit comments

Comments
 (0)