Skip to content

Commit 81d864d

Browse files
committed
test: 💍 prepared test utils
1 parent 8f9f9ba commit 81d864d

10 files changed

Lines changed: 187 additions & 50 deletions

File tree

__tests__/features/pan-touch/pan-touch.base.spec.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ describe("Pan Touch [Base]", () => {
1313
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
1414
});
1515
it("should return to position with padding enabled", async () => {
16-
const { content, touchPan, pinch } = renderApp({
17-
disablePadding: false,
16+
const { content, touchPan } = renderApp({
17+
alignmentAnimation: {
18+
disabled: false,
19+
},
1820
});
19-
pinch({ value: 1.2 });
2021
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
2122
touchPan({ x: 100, y: 100 });
2223
expect(content.style.transform).toBe("translate(100px, 100px) scale(1)");
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { waitFor } from "@testing-library/react";
2+
3+
import { renderApp, sleep } from "../../utils";
4+
5+
describe("Pan Touch [Velocity]", () => {
6+
describe("When panning to coords", () => {
7+
it("should trigger velocity", async () => {
8+
const { content, touchPan, pinch } = renderApp();
9+
pinch({ value: 1.5 });
10+
expect(content.style.transform).toBe("translate(0px, 0px) scale(1.5)");
11+
await sleep(10);
12+
touchPan({ x: 20, y: 20 });
13+
expect(content.style.transform).toBe("translate(20px, 20px) scale(1.5)");
14+
});
15+
// it("should not trigger disabled velocity", async () => {
16+
// const { content, touchPan, pinch } = renderApp({
17+
// disablePadding: false,
18+
// });
19+
// pinch({ value: 1.2 });
20+
// expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
21+
// touchPan({ x: 100, y: 100 });
22+
// expect(content.style.transform).toBe("translate(100px, 100px) scale(1)");
23+
// await waitFor(() => {
24+
// expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
25+
// });
26+
// });
27+
// it("should accelerate to certain point", async () => {
28+
// const { content, touchPan, zoom } = renderApp();
29+
// expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
30+
// zoom({ value: 1.5 });
31+
// expect(content.style.transform).toBe("translate(0px, 0px) scale(1.5)");
32+
// touchPan({ x: 100, y: 100 });
33+
// await sleep(10);
34+
// expect(content.style.transform).toBe(
35+
// "translate(100px, 100px) scale(1.5)",
36+
// );
37+
// });
38+
});
39+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { renderApp } from "../../utils";
2+
3+
describe("Pinch [Callbacks]", () => {
4+
describe("When pinch zooming", () => {
5+
it("should trigger onPinch callbacks", async () => {
6+
const spy1 = jest.fn();
7+
const spy2 = jest.fn();
8+
const spy3 = jest.fn();
9+
const { content, pinch } = renderApp({
10+
onPinchStart: spy1,
11+
onPinch: spy2,
12+
onPinchStop: spy3,
13+
});
14+
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
15+
pinch({ value: 2 });
16+
expect(spy1).toBeCalledTimes(1);
17+
expect(spy2).toBeCalled();
18+
expect(spy3).toBeCalledTimes(1);
19+
});
20+
21+
it("should not trigger onZoom callbacks", async () => {
22+
const spy1 = jest.fn();
23+
const spy2 = jest.fn();
24+
const spy3 = jest.fn();
25+
const { content, pinch } = renderApp({
26+
onZoomStart: spy1,
27+
onZoom: spy2,
28+
onZoomStop: spy3,
29+
});
30+
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
31+
pinch({ value: 2 });
32+
expect(spy1).toBeCalledTimes(0);
33+
expect(spy2).toBeCalledTimes(0);
34+
expect(spy3).toBeCalledTimes(0);
35+
});
36+
});
37+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { waitFor } from "@testing-library/dom";
2+
import { renderApp } from "../../utils";
3+
4+
describe("Zoom [Callbacks]", () => {
5+
describe("When wheel zooming", () => {
6+
it("should trigger onZoom callbacks", async () => {
7+
const spy1 = jest.fn();
8+
const spy2 = jest.fn();
9+
const spy3 = jest.fn();
10+
const { content, zoom } = renderApp({
11+
onZoomStart: spy1,
12+
onZoom: spy2,
13+
onZoomStop: spy3,
14+
});
15+
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
16+
zoom({ value: 2 });
17+
await waitFor(() => {
18+
expect(spy1).toBeCalledTimes(1);
19+
expect(spy2).toBeCalled();
20+
expect(spy3).toBeCalledTimes(1);
21+
});
22+
});
23+
24+
it("should not trigger onPinch callbacks", async () => {
25+
const spy1 = jest.fn();
26+
const spy2 = jest.fn();
27+
const spy3 = jest.fn();
28+
const { content, zoom } = renderApp({
29+
onPinchStart: spy1,
30+
onPinch: spy2,
31+
onPinchStop: spy3,
32+
});
33+
expect(content.style.transform).toBe("translate(0px, 0px) scale(1)");
34+
zoom({ value: 2 });
35+
expect(spy1).toBeCalledTimes(0);
36+
expect(spy2).toBeCalledTimes(0);
37+
expect(spy3).toBeCalledTimes(0);
38+
});
39+
});
40+
});

__tests__/utils/render-app.tsx

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ interface RenderApp {
2424
pinch: (options: { value: number; center?: [number, number] }) => void;
2525
}
2626

27+
const waitForPreviousActionToEnd = () => {
28+
// Synchronous await for 10ms to wait for the previous event to finish (pinching or touching)
29+
const startTime = Date.now();
30+
while (Date.now() - startTime < 10) {}
31+
};
32+
2733
function getPinchTouches(
2834
content: HTMLElement,
2935
center: [number, number],
@@ -95,7 +101,7 @@ export const renderApp = ({
95101
{...{ contentHeight, contentWidth, wrapperHeight, wrapperWidth }}
96102
/>,
97103
);
98-
// // controls buttons
104+
// controls buttons
99105
const zoomInBtn = screen.getByTestId("zoom-in");
100106
const zoomOutBtn = screen.getByTestId("zoom-out");
101107
const resetBtn = screen.getByTestId("reset");
@@ -147,6 +153,8 @@ export const renderApp = ({
147153
const { value, center = [0, 0] } = options;
148154
if (!ref.current) throw new Error("ref.current is null");
149155

156+
waitForPreviousActionToEnd();
157+
150158
const isZoomIn = ref.current.instance.state.scale < value;
151159
const from = isZoomIn ? 1 : 2;
152160
const step = 0.1;
@@ -169,9 +177,9 @@ export const renderApp = ({
169177
const scaleDifference = Math.abs(
170178
ref.current.instance.state.scale - value,
171179
);
172-
const isNearScale = scaleDifference < 0.5;
180+
const isNearScale = scaleDifference < 0.05;
173181

174-
const newStep = isNearScale ? step / 2 : step;
182+
const newStep = isNearScale ? step / 6 : step;
175183

176184
pinchValue = pinchValue + newStep;
177185
touches = getPinchTouches(content, center, pinchValue, from);
@@ -184,7 +192,9 @@ export const renderApp = ({
184192
}
185193
}
186194

187-
fireEvent.touchEnd(content);
195+
fireEvent.touchEnd(content, {
196+
touches,
197+
});
188198
};
189199

190200
const pan: RenderApp["pan"] = ({ x, y }) => {
@@ -196,17 +206,18 @@ export const renderApp = ({
196206
};
197207

198208
const touchPan: RenderApp["touchPan"] = ({ x, y }) => {
199-
const touches = [
200-
{
201-
pageX: 0,
202-
pageY: 0,
203-
clientX: 0,
204-
clientY: 0,
205-
target: content,
206-
},
207-
];
209+
waitForPreviousActionToEnd();
210+
208211
fireEvent.touchStart(content, {
209-
touches,
212+
touches: [
213+
{
214+
pageX: 0,
215+
pageY: 0,
216+
clientX: 0,
217+
clientY: 0,
218+
target: content,
219+
},
220+
],
210221
});
211222
fireEvent.touchMove(content, {
212223
touches: [
@@ -219,7 +230,17 @@ export const renderApp = ({
219230
},
220231
],
221232
});
222-
fireEvent.touchEnd(content);
233+
fireEvent.touchEnd(content, {
234+
touches: [
235+
{
236+
pageX: x,
237+
pageY: y,
238+
clientX: x,
239+
clientY: y,
240+
target: content,
241+
},
242+
],
243+
});
223244
};
224245

225246
return {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
"@storybook/react": "7.6.9",
5656
"@storybook/react-vite": "^7.6.9",
5757
"@storybook/test": "^7.6.9",
58-
"@testing-library/dom": "^8.20.0",
59-
"@testing-library/react": "^13.4.0",
58+
"@testing-library/dom": "^10.1.0",
59+
"@testing-library/react": "^16.0.0",
6060
"@testing-library/user-event": "^14.5.2",
6161
"@types/jest": "^26.0.22",
6262
"@types/node": "^15.6.1",

src/core/instance.core.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ export class ZoomPanPinch {
327327

328328
onPinchStart = (event: TouchEvent): void => {
329329
const { disabled } = this.setup;
330-
const { onPinchingStart, onZoomStart } = this.props;
330+
const { onPinchStart, onZoomStart } = this.props;
331331

332332
if (disabled) return;
333333

@@ -336,13 +336,13 @@ export class ZoomPanPinch {
336336

337337
handlePinchStart(this, event);
338338
handleCancelAnimation(this);
339-
handleCallback(getContext(this), event, onPinchingStart);
339+
handleCallback(getContext(this), event, onPinchStart);
340340
handleCallback(getContext(this), event, onZoomStart);
341341
};
342342

343343
onPinch = (event: TouchEvent): void => {
344344
const { disabled } = this.setup;
345-
const { onPinching, onZoom } = this.props;
345+
const { onPinch, onZoom } = this.props;
346346

347347
if (disabled) return;
348348

@@ -353,16 +353,16 @@ export class ZoomPanPinch {
353353
event.stopPropagation();
354354

355355
handlePinchZoom(this, event);
356-
handleCallback(getContext(this), event, onPinching);
356+
handleCallback(getContext(this), event, onPinch);
357357
handleCallback(getContext(this), event, onZoom);
358358
};
359359

360360
onPinchStop = (event: TouchEvent): void => {
361-
const { onPinchingStop, onZoomStop } = this.props;
361+
const { onPinchStop, onZoomStop } = this.props;
362362

363363
if (this.pinchStartScale) {
364364
handlePinchStop(this);
365-
handleCallback(getContext(this), event, onPinchingStop);
365+
handleCallback(getContext(this), event, onPinchStop);
366366
handleCallback(getContext(this), event, onZoomStop);
367367
}
368368
};
@@ -372,14 +372,15 @@ export class ZoomPanPinch {
372372
/// ///////
373373

374374
onTouchPanningStart = (event: TouchEvent): void => {
375-
const { disabled } = this.setup;
375+
const { disabled, doubleClick } = this.setup;
376376
const { onPanningStart } = this.props;
377377

378378
if (disabled) return;
379379

380+
const isDoubleTapAllowed = !doubleClick?.disabled;
380381
const isDoubleTap = this.lastTouch && +new Date() - this.lastTouch < 200;
381382

382-
if (isDoubleTap && event.touches.length === 1) {
383+
if (isDoubleTapAllowed && isDoubleTap && event.touches.length === 1) {
383384
this.onDoubleClick(event);
384385
} else {
385386
this.lastTouch = +new Date();

src/models/context.model.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ export type ReactZoomPanPinchProps = {
142142
ref: ReactZoomPanPinchRef,
143143
event: TouchEvent | MouseEvent,
144144
) => void;
145-
onPinchingStart?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
146-
onPinching?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
147-
onPinchingStop?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
145+
onPinchStart?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
146+
onPinch?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
147+
onPinchStop?: (ref: ReactZoomPanPinchRef, event: TouchEvent) => void;
148148
onZoomStart?: (
149149
ref: ReactZoomPanPinchRef,
150150
event: TouchEvent | MouseEvent,
@@ -192,9 +192,9 @@ export type LibrarySetup = Pick<
192192
| "onPanningStart"
193193
| "onPanning"
194194
| "onPanningStop"
195-
| "onPinchingStart"
196-
| "onPinching"
197-
| "onPinchingStop"
195+
| "onPinchStart"
196+
| "onPinch"
197+
| "onPinchStop"
198198
| "onZoomStart"
199199
| "onZoom"
200200
| "onZoomStop"

src/stories/docs/props.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,17 +495,17 @@ export const wrapperPropsTable: ComponentProps = {
495495
defaultValue: "undefined",
496496
description: "Callback fired when panning event has finished",
497497
},
498-
onPinchingStart: {
498+
onPinchStart: {
499499
type: ["(ref: ReactZoomPanPinchRef, event) => void"],
500500
defaultValue: "undefined",
501501
description: "Callback fired when pinch event has started",
502502
},
503-
onPinching: {
503+
onPinch: {
504504
type: ["(ref: ReactZoomPanPinchRef, event) => void"],
505505
defaultValue: "undefined",
506506
description: "Callback fired when pinch event is ongoing",
507507
},
508-
onPinchingStop: {
508+
onPinchStop: {
509509
type: ["(ref: ReactZoomPanPinchRef, event) => void"],
510510
defaultValue: "undefined",
511511
description: "Callback fired when pinch event has finished",

0 commit comments

Comments
 (0)