-
-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: update
useEventListener
composable (#1156)
- Loading branch information
Showing
13 changed files
with
282 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
packages/oruga/src/composables/tests/useClickOutside.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { describe, test, expect, vi, beforeEach, afterEach } from "vitest"; | ||
import { useClickOutside } from "../"; | ||
|
||
describe("useClickOutside test", () => { | ||
beforeEach(() => { | ||
vi.useFakeTimers(); | ||
}); | ||
|
||
afterEach(() => { | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
test("should call handler when clicking outside the element", () => { | ||
const handler = vi.fn(); | ||
const element = document.createElement("div"); | ||
document.body.appendChild(element); | ||
|
||
const stop = useClickOutside(element, handler, { immediate: true }); | ||
vi.runAllTimers(); | ||
|
||
// Simulate click outside | ||
document.body.dispatchEvent(new MouseEvent("click", { bubbles: true })); | ||
|
||
expect(handler).toHaveBeenCalled(); | ||
|
||
stop(); | ||
document.body.removeChild(element); | ||
}); | ||
|
||
test("should not call handler when clicking inside the element", () => { | ||
const handler = vi.fn(); | ||
const element = document.createElement("div"); | ||
document.body.appendChild(element); | ||
|
||
const stop = useClickOutside(element, handler, { immediate: true }); | ||
vi.runAllTimers(); | ||
|
||
// Simulate click inside | ||
element.dispatchEvent(new MouseEvent("click", { bubbles: true })); | ||
|
||
expect(handler).not.toHaveBeenCalled(); | ||
|
||
stop(); | ||
document.body.removeChild(element); | ||
}); | ||
|
||
test("should respect ignore option", () => { | ||
const handler = vi.fn(); | ||
const element = document.createElement("div"); | ||
const ignoreElement = document.createElement("div"); | ||
document.body.appendChild(element); | ||
document.body.appendChild(ignoreElement); | ||
|
||
const stop = useClickOutside([element, ignoreElement], handler, { | ||
immediate: true, | ||
}); | ||
vi.runAllTimers(); | ||
|
||
// Simulate click on ignored element | ||
ignoreElement.dispatchEvent(new MouseEvent("click", { bubbles: true })); | ||
|
||
expect(handler).not.toHaveBeenCalled(); | ||
|
||
stop(); | ||
document.body.removeChild(element); | ||
document.body.removeChild(ignoreElement); | ||
}); | ||
}); |
163 changes: 163 additions & 0 deletions
163
packages/oruga/src/composables/tests/useEventListener.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import { | ||
afterEach, | ||
beforeEach, | ||
describe, | ||
expect, | ||
test, | ||
vi, | ||
type MockInstance, | ||
} from "vitest"; | ||
import { effectScope, nextTick, ref, type Ref } from "vue"; | ||
|
||
import { useEventListener, type EventListenerOptions } from "../"; | ||
|
||
describe("useEventListener test", () => { | ||
const options: EventListenerOptions = { immediate: true }; | ||
let stop: () => void; | ||
let target: HTMLDivElement; | ||
let removeSpy: MockInstance; | ||
let addSpy: MockInstance; | ||
let listener: () => void; | ||
|
||
beforeEach(() => { | ||
vi.useFakeTimers(); | ||
target = document.createElement("div"); | ||
removeSpy = vi.spyOn(target, "removeEventListener"); | ||
addSpy = vi.spyOn(target, "addEventListener"); | ||
}); | ||
|
||
afterEach(() => { | ||
vi.restoreAllMocks(); | ||
}); | ||
|
||
test("should be defined", () => { | ||
expect(useEventListener).toBeDefined(); | ||
}); | ||
|
||
describe("given event", () => { | ||
const event = "click"; | ||
|
||
beforeEach(() => { | ||
listener = vi.fn(); | ||
}); | ||
|
||
test("should add listener", async () => { | ||
stop = useEventListener(target, event, listener, { | ||
immediate: true, | ||
}); | ||
vi.runAllTimers(); | ||
expect(addSpy).toBeCalledTimes(1); | ||
}); | ||
|
||
test("should trigger listener", () => { | ||
stop = useEventListener(target, event, listener, { | ||
immediate: true, | ||
}); | ||
vi.runAllTimers(); | ||
expect(listener).not.toBeCalled(); | ||
target.dispatchEvent(new MouseEvent(event)); | ||
expect(listener).toBeCalledTimes(1); | ||
}); | ||
|
||
test("should remove listener", () => { | ||
stop = useEventListener(target, event, listener, { | ||
immediate: true, | ||
}); | ||
vi.runAllTimers(); | ||
expect(removeSpy).not.toBeCalled(); | ||
|
||
stop(); | ||
|
||
expect(removeSpy).toBeCalledTimes(1); | ||
expect(removeSpy).toBeCalledWith(event, listener, options); | ||
}); | ||
}); | ||
|
||
describe("reactive target", () => { | ||
let target: Ref<HTMLDivElement | null>; | ||
|
||
beforeEach(() => { | ||
target = ref(document.createElement("div")); | ||
}); | ||
|
||
test("should not listen when target is invalid", async () => { | ||
useEventListener(target, "click", listener); | ||
const el = target.value; | ||
target.value = null; | ||
await nextTick(); | ||
el?.dispatchEvent(new MouseEvent("click")); | ||
await nextTick(); | ||
|
||
expect(listener).toHaveBeenCalledTimes(0); | ||
}); | ||
|
||
test(`should listen event`, async () => { | ||
useEventListener(target, "click", listener, { immediate: true }); | ||
vi.runAllTimers(); | ||
target.value!.dispatchEvent(new MouseEvent("click")); | ||
|
||
await nextTick(); | ||
|
||
expect(listener).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
test(`should manually stop listening event`, async () => { | ||
const stop = useEventListener(target, "click", listener, { | ||
immediate: true, | ||
}); | ||
|
||
stop(); | ||
|
||
target.value!.dispatchEvent(new MouseEvent("click")); | ||
|
||
await nextTick(); | ||
|
||
expect(listener).toHaveBeenCalledTimes(0); | ||
}); | ||
|
||
test(`should auto stop listening event`, async () => { | ||
const scope = effectScope(); | ||
await scope.run(async () => { | ||
useEventListener(target, "click", listener, { | ||
immediate: true, | ||
}); | ||
}); | ||
|
||
await scope.stop(); | ||
|
||
target.value!.dispatchEvent(new MouseEvent("click")); | ||
|
||
await nextTick(); | ||
|
||
expect(listener).toHaveBeenCalledTimes(0); | ||
}); | ||
}); | ||
|
||
test("should auto register on trigger", async () => { | ||
const trigger = ref(false); | ||
|
||
useEventListener(target, "click", listener, { trigger }); | ||
|
||
vi.runAllTimers(); | ||
expect(addSpy).toHaveBeenCalledTimes(0); | ||
|
||
trigger.value = true; | ||
await nextTick(); | ||
vi.runAllTimers(); | ||
|
||
expect(addSpy).toHaveBeenCalledTimes(1); | ||
expect(addSpy).toHaveBeenLastCalledWith("click", listener, { trigger }); | ||
expect(removeSpy).toHaveBeenCalledTimes(0); | ||
|
||
trigger.value = false; | ||
await nextTick(); | ||
vi.runAllTimers(); | ||
|
||
await nextTick(); | ||
expect(addSpy).toHaveBeenCalledTimes(1); | ||
expect(removeSpy).toHaveBeenCalledTimes(1); | ||
expect(removeSpy).toHaveBeenLastCalledWith("click", listener, { | ||
trigger, | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.