nandi/oripublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

ResizeHandle.test.tsx · 115 lines · 3.6 KBTypeScript Blame HistoryRaw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { fireEvent, render, screen } from "@testing-library/react";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import {
	KEYBOARD_RESIZE_STEP,
	ResizeHandle,
	widthAfterKey,
} from "./ResizeHandle";

// jsdom has no PointerEvent; a MouseEvent carrying a pointerId is enough for
// React's pointer handlers and gives the tests real clientX values.
beforeAll(() => {
	if (typeof window.PointerEvent === "undefined") {
		class PointerEventPolyfill extends MouseEvent {
			readonly pointerId: number;
			constructor(type: string, init: PointerEventInit = {}) {
				super(type, init);
				this.pointerId = init.pointerId ?? 0;
			}
		}
		Object.defineProperty(window, "PointerEvent", {
			value: PointerEventPolyfill,
			configurable: true,
		});
	}
});

const onResize = vi.fn();
const onReset = vi.fn();

function renderHandle(width = 200) {
	render(
		<ResizeHandle
			label="Resize the file tree"
			width={width}
			min={120}
			max={800}
			onResize={onResize}
			onReset={onReset}
		/>,
	);
	return screen.getByRole("separator", { name: "Resize the file tree" });
}

describe("ResizeHandle", () => {
	beforeEach(() => {
		onResize.mockReset();
		onReset.mockReset();
	});

	it("exposes the width through the separator pattern", () => {
		const handle = renderHandle(300);
		expect(handle.getAttribute("aria-orientation")).toBe("vertical");
		expect(handle.getAttribute("aria-valuenow")).toBe("300");
		expect(handle.getAttribute("aria-valuemin")).toBe("120");
		expect(handle.getAttribute("aria-valuemax")).toBe("800");
	});

	it("reports the width while dragging and stops on pointer up", () => {
		const handle = renderHandle(200);
		fireEvent.pointerDown(handle, { clientX: 500, pointerId: 1 });
		expect(handle.classList.contains("resize-handle-active")).toBe(true);

		fireEvent.pointerMove(handle, { clientX: 540, pointerId: 1 });
		fireEvent.pointerMove(handle, { clientX: 470, pointerId: 1 });
		expect(onResize.mock.calls).toEqual([[240], [170]]);

		fireEvent.pointerUp(handle, { clientX: 470, pointerId: 1 });
		expect(handle.classList.contains("resize-handle-active")).toBe(false);
		fireEvent.pointerMove(handle, { clientX: 600, pointerId: 1 });
		expect(onResize).toHaveBeenCalledTimes(2);
	});

	it("ignores pointer moves that did not start on the handle", () => {
		const handle = renderHandle(200);
		fireEvent.pointerMove(handle, { clientX: 600, pointerId: 1 });
		expect(onResize).not.toHaveBeenCalled();
	});

	it("resizes step by step with the arrow keys and jumps with Home / End", () => {
		const handle = renderHandle(200);
		fireEvent.keyDown(handle, { key: "ArrowRight" });
		fireEvent.keyDown(handle, { key: "ArrowLeft" });
		fireEvent.keyDown(handle, { key: "Home" });
		fireEvent.keyDown(handle, { key: "End" });
		expect(onResize.mock.calls).toEqual([
			[200 + KEYBOARD_RESIZE_STEP],
			[200 - KEYBOARD_RESIZE_STEP],
			[120],
			[800],
		]);
	});

	it("leaves other keys alone", () => {
		const handle = renderHandle(200);
		fireEvent.keyDown(handle, { key: "Enter" });
		fireEvent.keyDown(handle, { key: "Tab" });
		expect(onResize).not.toHaveBeenCalled();
	});

	it("resets on double-click", () => {
		const handle = renderHandle(200);
		fireEvent.doubleClick(handle);
		expect(onReset).toHaveBeenCalledTimes(1);
	});
});

describe("widthAfterKey", () => {
	it("maps the resize keys and returns null otherwise", () => {
		expect(widthAfterKey("ArrowRight", 200, 120, 800)).toBe(216);
		expect(widthAfterKey("ArrowLeft", 200, 120, 800)).toBe(184);
		expect(widthAfterKey("Home", 200, 120, 800)).toBe(120);
		expect(widthAfterKey("End", 200, 120, 800)).toBe(800);
		expect(widthAfterKey("a", 200, 120, 800)).toBeNull();
	});
});