mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-04-25 11:02:11 +00:00
125 lines
3.9 KiB
JavaScript
125 lines
3.9 KiB
JavaScript
import { mount, flushPromises } from "@vue/test-utils";
|
|
import { describe, it, expect, vi, beforeAll, afterEach } from "vitest";
|
|
import StickerView from "@/components/stickers/StickerView.vue";
|
|
|
|
const origIntersectionObserver = globalThis.IntersectionObserver;
|
|
|
|
beforeAll(() => {
|
|
const ctx = {
|
|
fillStyle: "",
|
|
strokeStyle: "",
|
|
fillRect: vi.fn(),
|
|
clearRect: vi.fn(),
|
|
save: vi.fn(),
|
|
restore: vi.fn(),
|
|
translate: vi.fn(),
|
|
scale: vi.fn(),
|
|
rotate: vi.fn(),
|
|
beginPath: vi.fn(),
|
|
closePath: vi.fn(),
|
|
moveTo: vi.fn(),
|
|
lineTo: vi.fn(),
|
|
arc: vi.fn(),
|
|
fill: vi.fn(),
|
|
stroke: vi.fn(),
|
|
setTransform: vi.fn(),
|
|
drawImage: vi.fn(),
|
|
measureText: vi.fn(() => ({ width: 0 })),
|
|
createLinearGradient: vi.fn(() => ({ addColorStop: vi.fn() })),
|
|
createRadialGradient: vi.fn(() => ({ addColorStop: vi.fn() })),
|
|
};
|
|
HTMLCanvasElement.prototype.getContext = vi.fn(() => ctx);
|
|
});
|
|
|
|
describe("StickerView.vue", () => {
|
|
it("renders img for static sticker", () => {
|
|
const w = mount(StickerView, {
|
|
props: {
|
|
src: "https://example.invalid/sticker.png",
|
|
imageType: "png",
|
|
alt: "x",
|
|
},
|
|
});
|
|
expect(w.find("img").exists()).toBe(true);
|
|
expect(w.find("video").exists()).toBe(false);
|
|
w.unmount();
|
|
});
|
|
|
|
it("renders video for webm", () => {
|
|
const w = mount(StickerView, {
|
|
props: {
|
|
src: "https://example.invalid/s.webm",
|
|
imageType: "webm",
|
|
},
|
|
});
|
|
expect(w.find("video").exists()).toBe(true);
|
|
w.unmount();
|
|
});
|
|
|
|
it("TGS renders placeholder without fetching sticker URL", async () => {
|
|
const baseFetch = globalThis.fetch;
|
|
const fetchSpy = vi.spyOn(globalThis, "fetch").mockImplementation((input, init) => baseFetch(input, init));
|
|
|
|
const w = mount(StickerView, {
|
|
props: {
|
|
src: "https://example.invalid/a.tgs",
|
|
imageType: "tgs",
|
|
},
|
|
attachTo: document.body,
|
|
});
|
|
|
|
await flushPromises();
|
|
expect(w.find("img").exists()).toBe(false);
|
|
expect(w.find(".w-full.h-full.flex").exists()).toBe(true);
|
|
const tgsCalls = fetchSpy.mock.calls.filter((c) => {
|
|
const u = typeof c[0] === "string" ? c[0] : (c[0]?.url ?? "");
|
|
return String(u).includes("example.invalid/a.tgs");
|
|
});
|
|
expect(tgsCalls.length).toBe(0);
|
|
|
|
fetchSpy.mockRestore();
|
|
w.unmount();
|
|
});
|
|
|
|
it("WebM calls play when in view and pause when out", async () => {
|
|
let ioCallback;
|
|
class MockIntersectionObserver {
|
|
constructor(cb) {
|
|
ioCallback = cb;
|
|
}
|
|
observe = vi.fn();
|
|
disconnect = vi.fn();
|
|
}
|
|
globalThis.IntersectionObserver = MockIntersectionObserver;
|
|
const playSpy = vi.spyOn(HTMLVideoElement.prototype, "play").mockResolvedValue(undefined);
|
|
const pauseSpy = vi.spyOn(HTMLVideoElement.prototype, "pause").mockImplementation(() => {});
|
|
|
|
const w = mount(StickerView, {
|
|
props: {
|
|
src: "https://example.invalid/s.webm",
|
|
imageType: "webm",
|
|
},
|
|
attachTo: document.body,
|
|
});
|
|
|
|
await flushPromises();
|
|
const root = w.vm.$refs.stickerRoot;
|
|
ioCallback([{ isIntersecting: true, target: root }]);
|
|
await flushPromises();
|
|
expect(playSpy).toHaveBeenCalled();
|
|
|
|
ioCallback([{ isIntersecting: false, target: root }]);
|
|
await flushPromises();
|
|
expect(pauseSpy).toHaveBeenCalled();
|
|
|
|
playSpy.mockRestore();
|
|
pauseSpy.mockRestore();
|
|
w.unmount();
|
|
});
|
|
|
|
afterEach(() => {
|
|
globalThis.IntersectionObserver = origIntersectionObserver;
|
|
vi.restoreAllMocks();
|
|
});
|
|
});
|