import React from "react";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
fireEvent,
render,
screen,
waitFor,
} from "../../../../../test/src/react-render.js";
import { TEST_CLIENT } from "../../../../../test/src/test-clients.js";
import {
IframePlayer,
LinkPlayer,
MediaRenderer,
mergeRefs,
} from "./MediaRenderer.js";
const three3dModelLink =
"https://i2.seadn.io/matic/0x2953399124f0cbb46d2cbacd8a89cf0599974963/bd1801876c5cf1302484e225c72959/49bd1801876c5cf1302484e225c72959.glb";
const imageLink =
"https://i2.seadn.io/ethereum/0xbd3531da5cf5857e7cfaa92426877b022e612cf8/750c4805cd12ea19c8c3909677e61988.png?w=350";
describe("MediaRenderer", () => {
it("should render nothing if no src provided", () => {
render();
expect(screen.queryByText("File")).not.toBeInTheDocument(); // would display file if it shows the "not found" div
});
it.skip("should render unknown if nothing found", () => {
render();
setTimeout(() => {
expect(screen.queryByText("File")).toBeInTheDocument(); // would display file if it shows the "not found" div
}, 1000);
});
it.skip("should render a plain image", async () => {
render();
await waitFor(() => {
expect(screen.getByRole("img")).toBeInTheDocument();
});
});
describe("mergeRefs", () => {
it("should call all callback refs with the given value", () => {
const callbackRef1 = vi.fn();
const callbackRef2 = vi.fn();
const mergedRef = mergeRefs([callbackRef1, callbackRef2]);
const testValue = { test: "value" };
mergedRef(testValue);
expect(callbackRef1).toHaveBeenCalledWith(testValue);
expect(callbackRef2).toHaveBeenCalledWith(testValue);
});
it("should assign the value to all mutable object refs", () => {
const mutableRef1 = React.createRef();
const mutableRef2 = React.createRef();
const mergedRef = mergeRefs([mutableRef1, mutableRef2]);
const testValue = { test: "value" };
mergedRef(testValue);
expect(mutableRef1.current).toBe(testValue);
expect(mutableRef2.current).toBe(testValue);
});
it("should handle a mix of callback and mutable object refs", () => {
const callbackRef = vi.fn();
const mutableRef = React.createRef();
const mergedRef = mergeRefs([callbackRef, mutableRef]);
const testValue = { test: "value" };
mergedRef(testValue);
expect(callbackRef).toHaveBeenCalledWith(testValue);
expect(mutableRef.current).toBe(testValue);
});
it("should do nothing if refs array is empty", () => {
const mergedRef = mergeRefs([]);
expect(() => mergedRef(null)).not.toThrow();
});
});
describe("LinkPlayer", () => {
it("renders with default props", () => {
render();
const linkElement = screen.getByText("File");
expect(linkElement).toBeInTheDocument();
expect(linkElement.tagName).toBe("A");
expect(linkElement).toHaveAttribute("target", "_blank");
expect(linkElement).toHaveAttribute("rel", "noopener noreferrer");
});
it("renders with custom src and alt", () => {
const src = "https://example.com/file";
const alt = "Custom File Name";
render();
const linkElement = screen.getByText(alt);
expect(linkElement).toBeInTheDocument();
expect(linkElement).toHaveAttribute("href", src);
});
it("applies custom style and className", () => {
const customStyle = { backgroundColor: "red" };
const customClassName = "custom-class";
const { container } = render(
,
);
const outerDiv = container.querySelector(".custom-class");
if (!outerDiv) {
throw new Error("Failed to render LinkPlayer");
}
const styles = window.getComputedStyle(outerDiv);
expect(styles.backgroundColor).toBe("red");
});
it("forwards ref to anchor element", () => {
const ref = React.createRef();
render();
expect(ref.current).toBeInstanceOf(HTMLAnchorElement);
});
});
describe("IframePlayer", () => {
beforeEach(() => {
// Reset the body before each test
document.body.innerHTML = "";
});
it("renders with default props", () => {
render();
const iframe = screen.getByTitle("thirdweb iframe player");
expect(iframe).toBeInTheDocument();
expect(iframe.tagName).toBe("IFRAME");
expect(iframe).toHaveAttribute("sandbox", "allow-scripts");
expect(iframe).toHaveAttribute(
"allow",
"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",
);
});
it("applies custom src and alt", () => {
const src = "https://example.com/video";
const alt = "Custom Video";
render();
const iframe = screen.getByTitle(alt);
expect(iframe).toBeInTheDocument();
expect(iframe).toHaveAttribute("src", src);
});
it("renders poster image when provided", () => {
const poster = "https://example.com/poster.jpg";
render();
const posterImg = screen.getByRole("img");
expect(posterImg).toBeInTheDocument();
expect(posterImg).toHaveAttribute("src", poster);
});
it("toggles play state when PlayButton is clicked", async () => {
render();
const playButton = screen.getByRole("button");
expect(playButton).toBeInTheDocument();
const iframe = screen.getByTitle("thirdweb iframe player");
expect(iframe).toHaveAttribute("src", "https://example.com/video");
fireEvent.click(playButton);
// After clicking, the iframe src should be undefined
expect(iframe).not.toHaveAttribute("src");
fireEvent.click(playButton);
// After clicking again, the iframe src should be restored
expect(iframe).toHaveAttribute("src", "https://example.com/video");
});
it("applies custom style", () => {
const customStyle = { backgroundColor: "red" };
const { container } = render(
,
);
const element = container.querySelector(".iframe-test");
if (!element) {
throw new Error("no iframe detected");
}
expect(element).toHaveStyle("background-color: red");
});
it("forwards ref to iframe element", () => {
const ref = React.createRef();
render();
expect(ref.current).toBeInstanceOf(HTMLIFrameElement);
});
it("respects requireInteraction prop", () => {
render(
,
);
const iframe = screen.getByTitle("thirdweb iframe player");
expect(iframe).not.toHaveAttribute("src");
const playButton = screen.getByRole("button");
fireEvent.click(playButton);
expect(iframe).toHaveAttribute("src", "https://example.com/video");
});
});
it("should render poster image for 3d models", async () => {
render(
,
);
await waitFor(() => {
expect(screen.getByRole("img")).toBeInTheDocument();
});
});
});