react-resizable-panels
Version:
React components for resizable panel groups/layouts
205 lines (177 loc) • 4.57 kB
text/typescript
import { assert } from "./assert";
const util = require("util");
export function dispatchPointerEvent(type: string, target: HTMLElement) {
const rect = target.getBoundingClientRect();
const clientX = rect.left + rect.width / 2;
const clientY = rect.top + rect.height / 2;
const event = new MouseEvent(type, {
bubbles: true,
clientX,
clientY,
});
Object.defineProperties(event, {
pageX: {
get() {
return clientX;
},
},
pageY: {
get() {
return clientY;
},
},
isPrimary: {
value: true,
},
});
target.dispatchEvent(event);
}
export function expectToBeCloseToArray(
actualNumbers: number[],
expectedNumbers: number[]
) {
expect(actualNumbers.length).toBe(expectedNumbers.length);
try {
actualNumbers.forEach((actualNumber, index) => {
const expectedNumber = expectedNumbers[index];
assert(expectedNumber != null, `Expected number not found`);
expect(actualNumber).toBeCloseTo(expectedNumber, 1);
});
} catch (error) {
expect(actualNumbers).toEqual(expectedNumbers);
}
}
export function mockBoundingClientRect(
element: HTMLElement,
rect: {
height: number;
width: number;
x: number;
y: number;
}
) {
const { height, width, x, y } = rect;
Object.defineProperty(element, "getBoundingClientRect", {
configurable: true,
value: () =>
({
bottom: y + height,
height,
left: x,
right: x + width,
toJSON() {
return "";
},
top: y,
width,
x,
y,
}) satisfies DOMRect,
});
}
export function mockPanelGroupOffsetWidthAndHeight(
mockWidth = 1_000,
mockHeight = 1_000
) {
const offsetHeightPropertyDescriptor = Object.getOwnPropertyDescriptor(
HTMLElement.prototype,
"offsetHeight"
);
const offsetWidthPropertyDescriptor = Object.getOwnPropertyDescriptor(
HTMLElement.prototype,
"offsetWidth"
);
Object.defineProperty(HTMLElement.prototype, "offsetHeight", {
configurable: true,
get: function () {
if (this.hasAttribute("data-resize-handle")) {
return 0;
} else if (this.hasAttribute("data-panel-group")) {
return mockHeight;
}
},
});
Object.defineProperty(HTMLElement.prototype, "offsetWidth", {
configurable: true,
get: function () {
if (this.hasAttribute("data-resize-handle")) {
return 0;
} else if (this.hasAttribute("data-panel-group")) {
return mockWidth;
}
},
});
return function uninstallMocks() {
if (offsetHeightPropertyDescriptor) {
Object.defineProperty(
HTMLElement.prototype,
"offsetHeight",
offsetHeightPropertyDescriptor
);
}
if (offsetWidthPropertyDescriptor) {
Object.defineProperty(
HTMLElement.prototype,
"offsetWidth",
offsetWidthPropertyDescriptor
);
}
};
}
export function verifyAttribute(
element: HTMLElement,
attributeName: string,
expectedValue: string | null
) {
const actualValue = element.getAttribute(attributeName);
expect(actualValue).toBe(expectedValue);
}
export function verifyExpandedPanelGroupLayout(
actualLayout: number[],
expectedLayout: number[]
) {
expect(actualLayout).toEqual(expectedLayout);
}
export function verifyExpectedWarnings(
callback: Function,
...expectedMessages: string[]
) {
const consoleSpy = (format: any, ...args: any[]) => {
const message = util.format(format, ...args);
for (let index = 0; index < expectedMessages.length; index++) {
const expectedMessage = expectedMessages[index];
if (message.includes(expectedMessage)) {
expectedMessages.splice(index, 1);
return;
}
}
if (expectedMessages.length === 0) {
throw new Error(`Unexpected message recorded:\n\n${message}`);
}
};
const originalError = console.error;
const originalWarn = console.warn;
console.error = consoleSpy;
console.warn = consoleSpy;
let caughtError;
let didCatch = false;
try {
callback();
} catch (error) {
caughtError = error;
didCatch = true;
} finally {
console.error = originalError;
console.warn = originalWarn;
if (didCatch) {
throw caughtError;
}
// Any remaining messages indicate a failed expectations.
if (expectedMessages.length > 0) {
throw Error(
`Expected message(s) not recorded:\n\n${expectedMessages.join("\n")}`
);
}
return { pass: true };
}
}