mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2026-05-25 08:18:37 +00:00
361 lines
10 KiB
TypeScript
361 lines
10 KiB
TypeScript
/**
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import { nextTick } from "vue";
|
|
import { useTimeoutFn, useTimeoutRef } from "../useTimeout";
|
|
|
|
describe("useTimeout", () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
vi.clearAllTimers();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.runOnlyPendingTimers();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
describe("useTimeoutRef", () => {
|
|
it("should initialize with readyRef as false", () => {
|
|
const { readyRef } = useTimeoutRef(1000);
|
|
expect(readyRef.value).toBe(false);
|
|
});
|
|
|
|
it("should set readyRef to true after timeout", async () => {
|
|
const { readyRef } = useTimeoutRef(1000);
|
|
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should start timer immediately", () => {
|
|
const { readyRef } = useTimeoutRef(500);
|
|
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(500);
|
|
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should provide stop function that clears timer", () => {
|
|
const { readyRef, stop } = useTimeoutRef(1000);
|
|
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
stop();
|
|
vi.advanceTimersByTime(1000);
|
|
|
|
expect(readyRef.value).toBe(false);
|
|
});
|
|
|
|
it("should provide start function that restarts timer", () => {
|
|
const { readyRef, start } = useTimeoutRef(1000);
|
|
|
|
// Wait for initial timer
|
|
vi.advanceTimersByTime(1000);
|
|
expect(readyRef.value).toBe(true);
|
|
|
|
// Reset and restart
|
|
start();
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should handle multiple start calls", () => {
|
|
const { readyRef, start } = useTimeoutRef(1000);
|
|
|
|
// Call start multiple times
|
|
start();
|
|
start();
|
|
start();
|
|
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should handle zero timeout", () => {
|
|
const { readyRef } = useTimeoutRef(0);
|
|
|
|
vi.advanceTimersByTime(0);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should handle negative timeout", () => {
|
|
const { readyRef } = useTimeoutRef(-1000);
|
|
|
|
vi.advanceTimersByTime(0);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should return all required functions and refs", () => {
|
|
const result = useTimeoutRef(1000);
|
|
|
|
expect(result).toHaveProperty("readyRef");
|
|
expect(result).toHaveProperty("stop");
|
|
expect(result).toHaveProperty("start");
|
|
expect(typeof result.stop).toBe("function");
|
|
expect(typeof result.start).toBe("function");
|
|
});
|
|
});
|
|
|
|
describe("useTimeoutFn", () => {
|
|
it("should call handle function after timeout when native is false", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
expect(mockHandle).not.toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should call handle function immediately when native is true", () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef } = useTimeoutFn(mockHandle, 1000, true);
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(readyRef.value).toBe(false);
|
|
});
|
|
|
|
it("should not call handle function immediately when native is false", () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
expect(mockHandle).not.toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(false);
|
|
});
|
|
|
|
it("should provide stop function that prevents handle execution", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef, stop } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
stop();
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).not.toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(false);
|
|
});
|
|
|
|
it("should provide start function that restarts timeout", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef, start } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
// Wait for initial timeout
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
|
|
// Reset and restart
|
|
start();
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
// Wait a bit more for reactivity to update
|
|
await nextTick();
|
|
// The handle should be called at least once, and readyRef should be true
|
|
expect(mockHandle).toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should handle handle function that returns a value", async () => {
|
|
const mockHandle = vi.fn(() => "test result");
|
|
useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(mockHandle).toHaveReturnedWith("test result");
|
|
});
|
|
|
|
it("should handle handle function that throws an error", async () => {
|
|
const mockHandle = vi.fn(() => {
|
|
throw new Error("Test error");
|
|
});
|
|
|
|
// Use try-catch to handle the error that will be thrown by the watch
|
|
try {
|
|
useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
} catch (error) {
|
|
// The error is expected to be thrown by the watch function
|
|
expect(error).toBeInstanceOf(Error);
|
|
expect((error as Error).message).toBe("Test error");
|
|
}
|
|
});
|
|
|
|
it("should work with async handle function", async () => {
|
|
const mockHandle = vi.fn(async () => {
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
return "async result";
|
|
});
|
|
|
|
useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("should handle multiple timeout executions", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef, start } = useTimeoutFn(mockHandle, 500, false);
|
|
|
|
// First execution
|
|
vi.advanceTimersByTime(500);
|
|
await nextTick();
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
|
|
// Second execution
|
|
start();
|
|
vi.advanceTimersByTime(500);
|
|
await nextTick();
|
|
await nextTick();
|
|
expect(mockHandle).toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(true);
|
|
|
|
// Third execution
|
|
start();
|
|
vi.advanceTimersByTime(500);
|
|
await nextTick();
|
|
await nextTick();
|
|
expect(mockHandle).toHaveBeenCalled();
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should return all required functions and refs", () => {
|
|
const mockHandle = vi.fn();
|
|
const result = useTimeoutFn(mockHandle, 1000);
|
|
|
|
expect(result).toHaveProperty("readyRef");
|
|
expect(result).toHaveProperty("stop");
|
|
expect(result).toHaveProperty("start");
|
|
expect(typeof result.stop).toBe("function");
|
|
expect(typeof result.start).toBe("function");
|
|
});
|
|
|
|
it("should throw error when handle is not a function", () => {
|
|
expect(() => {
|
|
useTimeoutFn("not a function" as any, 1000);
|
|
}).toThrow("handle is not Function!");
|
|
});
|
|
|
|
it("should throw error when handle is null", () => {
|
|
expect(() => {
|
|
useTimeoutFn(null as any, 1000);
|
|
}).toThrow("handle is not Function!");
|
|
});
|
|
|
|
it("should throw error when handle is undefined", () => {
|
|
expect(() => {
|
|
useTimeoutFn(undefined as any, 1000);
|
|
}).toThrow("handle is not Function!");
|
|
});
|
|
|
|
it("should handle zero wait time", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef } = useTimeoutFn(mockHandle, 0, false);
|
|
|
|
vi.advanceTimersByTime(0);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
|
|
it("should handle negative wait time", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef } = useTimeoutFn(mockHandle, -1000, false);
|
|
|
|
vi.advanceTimersByTime(0);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("Integration tests", () => {
|
|
it("should work together with Vue reactivity", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef, stop, start } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
// Initial state
|
|
expect(readyRef.value).toBe(false);
|
|
expect(mockHandle).not.toHaveBeenCalled();
|
|
|
|
// After timeout
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
expect(readyRef.value).toBe(true);
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
|
|
// After stop
|
|
stop();
|
|
expect(readyRef.value).toBe(false);
|
|
|
|
// After restart
|
|
start();
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
await nextTick();
|
|
expect(readyRef.value).toBe(true);
|
|
expect(mockHandle).toHaveBeenCalled();
|
|
});
|
|
|
|
it("should handle rapid start/stop calls", async () => {
|
|
const mockHandle = vi.fn();
|
|
const { readyRef, stop, start } = useTimeoutFn(mockHandle, 1000, false);
|
|
|
|
// Rapid start/stop calls
|
|
start();
|
|
stop();
|
|
start();
|
|
stop();
|
|
start();
|
|
|
|
vi.advanceTimersByTime(1000);
|
|
await nextTick();
|
|
|
|
expect(mockHandle).toHaveBeenCalledTimes(1);
|
|
expect(readyRef.value).toBe(true);
|
|
});
|
|
});
|
|
});
|