mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-04-27 19:25:58 +00:00
91 lines
3.3 KiB
JavaScript
91 lines
3.3 KiB
JavaScript
import { readFileSync } from "fs";
|
|
import { join } from "path";
|
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
import { clampFloatingToViewport } from "../../meshchatx/src/frontend/js/clampFloatingToViewport.js";
|
|
|
|
function readSource(relativePath) {
|
|
return readFileSync(join(process.cwd(), relativePath), "utf8");
|
|
}
|
|
|
|
describe("clampFloatingToViewport", () => {
|
|
let innerWidth;
|
|
let innerHeight;
|
|
|
|
beforeEach(() => {
|
|
innerWidth = 800;
|
|
innerHeight = 600;
|
|
Object.defineProperty(window, "innerWidth", {
|
|
configurable: true,
|
|
get: () => innerWidth,
|
|
});
|
|
Object.defineProperty(window, "innerHeight", {
|
|
configurable: true,
|
|
get: () => innerHeight,
|
|
});
|
|
});
|
|
|
|
it("returns preferred position when panel fits inside the viewport", () => {
|
|
const { left, top, maxHeight } = clampFloatingToViewport(100, 120, 200, 150);
|
|
expect(left).toBe(100);
|
|
expect(top).toBe(120);
|
|
expect(maxHeight).toBeNull();
|
|
});
|
|
|
|
it("shifts left when the panel would extend past the right edge", () => {
|
|
const w = 200;
|
|
const { left, top, maxHeight } = clampFloatingToViewport(700, 50, w, 100);
|
|
expect(left).toBe(800 - w - 8);
|
|
expect(top).toBe(50);
|
|
expect(maxHeight).toBeNull();
|
|
});
|
|
|
|
it("shifts up when the panel would extend past the bottom edge", () => {
|
|
const h = 200;
|
|
const { left, top, maxHeight } = clampFloatingToViewport(40, 520, 160, h);
|
|
expect(left).toBe(40);
|
|
expect(top).toBe(600 - h - 8);
|
|
expect(maxHeight).toBeNull();
|
|
});
|
|
|
|
it("uses custom margin", () => {
|
|
const w = 100;
|
|
const { left } = clampFloatingToViewport(790, 10, w, 50, { margin: 16 });
|
|
expect(left).toBe(800 - w - 16);
|
|
});
|
|
|
|
it("returns maxHeight when content is taller than the viewport allows", () => {
|
|
innerHeight = 400;
|
|
Object.defineProperty(window, "innerHeight", {
|
|
configurable: true,
|
|
get: () => innerHeight,
|
|
});
|
|
const { left, top, maxHeight } = clampFloatingToViewport(10, 10, 200, 900);
|
|
expect(left).toBe(10);
|
|
expect(top).toBe(8);
|
|
expect(maxHeight).toBe(400 - 16);
|
|
});
|
|
|
|
it("pins wide panels to the left margin when wider than usable width", () => {
|
|
innerWidth = 300;
|
|
Object.defineProperty(window, "innerWidth", {
|
|
configurable: true,
|
|
get: () => innerWidth,
|
|
});
|
|
const { left } = clampFloatingToViewport(50, 10, 500, 40);
|
|
expect(left).toBe(8);
|
|
});
|
|
});
|
|
|
|
describe("clampFloatingToViewport wiring", () => {
|
|
it.each([
|
|
["DropDownMenu.vue", "meshchatx/src/frontend/components/DropDownMenu.vue", 'ref="dropdownPanel"'],
|
|
["LanguageSelector.vue", "meshchatx/src/frontend/components/LanguageSelector.vue", 'ref="languageDropdown"'],
|
|
["NotificationBell.vue", "meshchatx/src/frontend/components/NotificationBell.vue", 'ref="notificationDropdown"'],
|
|
["ConversationViewer.vue", "meshchatx/src/frontend/components/messages/ConversationViewer.vue", "onReactionPickerDragStart"],
|
|
])("%s imports the helper and clamps floating UI", (_, relativePath, anchor) => {
|
|
const src = readSource(relativePath);
|
|
expect(src).toContain("clampFloatingToViewport");
|
|
expect(src).toContain(anchor);
|
|
});
|
|
});
|