Files
MeshChatX/tests/frontend/InViewAnimatedImg.test.js

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();
});
});