mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
- npm-run-all → npm-run-all2 (dev script uses run-p) - lint-staged → nano-staged (config block + husky hook) - lodash.debounce → local src/utils/debounce.ts with cancel/flush/leading/trailing - dotenv → process.loadEnvFile in integration test bootstrap - eslint-plugin-react → @eslint-react/eslint-plugin (flat-config migration) - js-yaml → yaml (mock + jest CJS moduleNameMapper for jsdom) - crypto-js → pure-JS md5/sha256 in src/utils/hash.ts producing byte-identical digests so all on-disk cache keys (PDF, file, project, search index) remain valid across the upgrade — no migration or re-parse cost Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { debounce } from "./debounce";
|
|
|
|
jest.useFakeTimers();
|
|
|
|
describe("debounce", () => {
|
|
it("invokes once after the wait period with the latest args (trailing default)", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100);
|
|
|
|
d("a");
|
|
d("b");
|
|
d("c");
|
|
|
|
expect(fn).not.toHaveBeenCalled();
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
expect(fn).toHaveBeenCalledWith("c");
|
|
});
|
|
|
|
it("supports leading-only mode", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100, { leading: true, trailing: false });
|
|
|
|
d("a");
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
expect(fn).toHaveBeenCalledWith("a");
|
|
|
|
d("b");
|
|
d("c");
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("fires both edges when leading and trailing are true and there are multiple calls", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100, { leading: true, trailing: true });
|
|
|
|
d("a");
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
expect(fn).toHaveBeenLastCalledWith("a");
|
|
|
|
d("b");
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).toHaveBeenCalledTimes(2);
|
|
expect(fn).toHaveBeenLastCalledWith("b");
|
|
});
|
|
|
|
it("does not fire trailing if leading already covered the single call", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100, { leading: true, trailing: true });
|
|
|
|
d("only");
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("cancel prevents pending trailing invocation", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100);
|
|
|
|
d("a");
|
|
d.cancel();
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("flush invokes the pending call synchronously", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100);
|
|
|
|
d("a");
|
|
d.flush();
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
expect(fn).toHaveBeenCalledWith("a");
|
|
jest.advanceTimersByTime(100);
|
|
expect(fn).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("flush is a no-op when nothing is pending", () => {
|
|
const fn = jest.fn();
|
|
const d = debounce(fn, 100);
|
|
expect(d.flush()).toBeUndefined();
|
|
expect(fn).not.toHaveBeenCalled();
|
|
});
|
|
});
|