134 lines
3.2 KiB
TypeScript
134 lines
3.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
resolveChatKeyboardFallbackInset,
|
|
resolveChatKeyboardInset,
|
|
type ChatKeyboardViewportBaseline,
|
|
type ChatKeyboardViewportSnapshot,
|
|
} from "../chat-keyboard-geometry";
|
|
|
|
const baseline: ChatKeyboardViewportBaseline = {
|
|
layoutHeight: 800,
|
|
layoutWidth: 390,
|
|
visualHeight: 760,
|
|
};
|
|
|
|
function makeSnapshot(
|
|
overrides: Partial<ChatKeyboardViewportSnapshot> = {},
|
|
): ChatKeyboardViewportSnapshot {
|
|
return {
|
|
layoutHeight: 800,
|
|
visualHeight: 760,
|
|
visualScale: 1,
|
|
virtualKeyboardHeight: 0,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("resolveChatKeyboardInset", () => {
|
|
it("does not add an inset when the content viewport already resized", () => {
|
|
expect(
|
|
resolveChatKeyboardInset(
|
|
baseline,
|
|
makeSnapshot({ layoutHeight: 500, visualHeight: 500 }),
|
|
),
|
|
).toEqual({
|
|
keyboardVisible: true,
|
|
bottomInset: 0,
|
|
source: "content-resize",
|
|
});
|
|
});
|
|
|
|
it("uses the visual viewport occlusion with the target gap", () => {
|
|
expect(
|
|
resolveChatKeyboardInset(
|
|
baseline,
|
|
makeSnapshot({ visualHeight: 460 }),
|
|
),
|
|
).toEqual({
|
|
keyboardVisible: true,
|
|
bottomInset: 316,
|
|
source: "visual-viewport",
|
|
});
|
|
});
|
|
|
|
it("prefers Virtual Keyboard geometry when available", () => {
|
|
expect(
|
|
resolveChatKeyboardInset(
|
|
baseline,
|
|
makeSnapshot({
|
|
visualHeight: 520,
|
|
virtualKeyboardHeight: 320,
|
|
}),
|
|
),
|
|
).toEqual({
|
|
keyboardVisible: true,
|
|
bottomInset: 336,
|
|
source: "virtual-keyboard",
|
|
});
|
|
});
|
|
|
|
it("ignores visual viewport changes caused by page zoom", () => {
|
|
expect(
|
|
resolveChatKeyboardInset(
|
|
baseline,
|
|
makeSnapshot({ visualHeight: 460, visualScale: 1.2 }),
|
|
),
|
|
).toEqual({
|
|
keyboardVisible: false,
|
|
bottomInset: 0,
|
|
source: "none",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("resolveChatKeyboardFallbackInset", () => {
|
|
it.each([
|
|
[{ layoutWidth: 320, layoutHeight: 568 }, 260],
|
|
[{ layoutWidth: 360, layoutHeight: 640 }, 291],
|
|
[{ layoutWidth: 390, layoutHeight: 844 }, 344],
|
|
[{ layoutWidth: 430, layoutHeight: 932 }, 356],
|
|
])("fits common viewport %o", (viewport, expectedInset) => {
|
|
expect(resolveChatKeyboardFallbackInset(viewport)).toBe(expectedInset);
|
|
});
|
|
|
|
it("covers the reported 392 by 760 Facebook viewport", () => {
|
|
expect(
|
|
resolveChatKeyboardFallbackInset({
|
|
layoutWidth: 392,
|
|
layoutHeight: 760,
|
|
}),
|
|
).toBe(343);
|
|
});
|
|
|
|
it("stays stable across tall viewports with the same width", () => {
|
|
expect(
|
|
resolveChatKeyboardFallbackInset({
|
|
layoutWidth: 390,
|
|
layoutHeight: 760,
|
|
}),
|
|
).toBe(343);
|
|
expect(
|
|
resolveChatKeyboardFallbackInset({
|
|
layoutWidth: 390,
|
|
layoutHeight: 900,
|
|
}),
|
|
).toBe(344);
|
|
});
|
|
|
|
it("keeps the keyboard estimate within its bounds", () => {
|
|
expect(
|
|
resolveChatKeyboardFallbackInset({
|
|
layoutWidth: 300,
|
|
layoutHeight: 400,
|
|
}),
|
|
).toBe(256);
|
|
expect(
|
|
resolveChatKeyboardFallbackInset({
|
|
layoutWidth: 600,
|
|
layoutHeight: 1_000,
|
|
}),
|
|
).toBe(356);
|
|
});
|
|
});
|