mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-04-25 08:52:15 +00:00
130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
import { mount, flushPromises } from "@vue/test-utils";
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
import InViewAnimatedImg from "@/components/messages/InViewAnimatedImg.vue";
|
|
|
|
describe("InViewAnimatedImg.vue", () => {
|
|
const origIo = globalThis.IntersectionObserver;
|
|
|
|
afterEach(() => {
|
|
globalThis.IntersectionObserver = origIo;
|
|
vi.restoreAllMocks();
|
|
});
|
|
|
|
it("shows img immediately when IntersectionObserver is unavailable (fallback)", async () => {
|
|
globalThis.IntersectionObserver = undefined;
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: {
|
|
src: "https://example.invalid/a.gif",
|
|
imgClass: "w-full h-8",
|
|
},
|
|
});
|
|
await flushPromises();
|
|
expect(w.find("img").exists()).toBe(true);
|
|
expect(w.find("img").attributes("src")).toBe("https://example.invalid/a.gif");
|
|
expect(w.find("div[aria-hidden=true]").exists()).toBe(false);
|
|
w.unmount();
|
|
});
|
|
|
|
it("shows placeholder until intersecting when observer fires false then true", async () => {
|
|
let callback;
|
|
class MockIntersectionObserver {
|
|
constructor(cb) {
|
|
callback = cb;
|
|
}
|
|
observe = vi.fn();
|
|
disconnect = vi.fn();
|
|
}
|
|
globalThis.IntersectionObserver = MockIntersectionObserver;
|
|
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: {
|
|
src: "https://example.invalid/b.gif",
|
|
imgClass: "test-img",
|
|
},
|
|
attachTo: document.body,
|
|
});
|
|
|
|
await flushPromises();
|
|
expect(w.find("img").exists()).toBe(false);
|
|
|
|
const wrap = w.vm.$refs.wrap;
|
|
callback([{ isIntersecting: true, target: wrap }]);
|
|
await flushPromises();
|
|
|
|
expect(w.find("img").exists()).toBe(true);
|
|
expect(w.find("img").classes()).toContain("test-img");
|
|
w.unmount();
|
|
});
|
|
|
|
it("hides img when intersection becomes false", async () => {
|
|
let callback;
|
|
class MockIntersectionObserver {
|
|
constructor(cb) {
|
|
callback = cb;
|
|
}
|
|
observe = vi.fn();
|
|
disconnect = vi.fn();
|
|
}
|
|
globalThis.IntersectionObserver = MockIntersectionObserver;
|
|
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: { src: "https://example.invalid/c.gif", imgClass: "x" },
|
|
attachTo: document.body,
|
|
});
|
|
await flushPromises();
|
|
|
|
const wrap = w.vm.$refs.wrap;
|
|
callback([{ isIntersecting: true, target: wrap }]);
|
|
await flushPromises();
|
|
expect(w.find("img").exists()).toBe(true);
|
|
|
|
callback([{ isIntersecting: false, target: wrap }]);
|
|
await flushPromises();
|
|
expect(w.find("img").exists()).toBe(false);
|
|
|
|
w.unmount();
|
|
});
|
|
|
|
it("disconnects observer on unmount", async () => {
|
|
const disconnect = vi.fn();
|
|
class MockIntersectionObserver {
|
|
constructor() {
|
|
this.observe = vi.fn();
|
|
this.disconnect = disconnect;
|
|
}
|
|
}
|
|
globalThis.IntersectionObserver = MockIntersectionObserver;
|
|
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: { src: "https://example.invalid/d.gif" },
|
|
});
|
|
await flushPromises();
|
|
w.unmount();
|
|
expect(disconnect).toHaveBeenCalled();
|
|
});
|
|
|
|
it("emits click from img", async () => {
|
|
globalThis.IntersectionObserver = undefined;
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: { src: "https://example.invalid/e.gif" },
|
|
});
|
|
await flushPromises();
|
|
await w.find("img").trigger("click");
|
|
expect(w.emitted("click")).toBeTruthy();
|
|
w.unmount();
|
|
});
|
|
|
|
it("uses fit-parent placeholder classes", async () => {
|
|
globalThis.IntersectionObserver = undefined;
|
|
const w = mount(InViewAnimatedImg, {
|
|
props: {
|
|
src: "https://example.invalid/f.gif",
|
|
fitParent: true,
|
|
},
|
|
});
|
|
await flushPromises();
|
|
expect(w.vm.$el.className).toContain("absolute");
|
|
w.unmount();
|
|
});
|
|
});
|