UNPKG

react-sass-inlinesvg

Version:
598 lines (597 loc) 31 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const react_1 = __importDefault(require("react")); const react_2 = require("@testing-library/react"); const jest_fetch_mock_1 = __importStar(require("jest-fetch-mock")); require("@testing-library/jest-dom/extend-expect"); const Svg_1 = require("../Svg"); (0, jest_fetch_mock_1.enableFetchMocks)(); jest.spyOn(global, "setTimeout"); const fooIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><polygon points=""/></svg>`; const barIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><path d="" style="fill-rule:evenodd"/></svg>`; const titleDescriptionIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><title>TITLE</title><desc>DESC</desc></svg>`; const playSvg = fs_1.default.readFileSync(__dirname + "/__fixtures__/play.svg", "utf8"); const datahrefSvg = fs_1.default.readFileSync(__dirname + "/__fixtures__/datahref.svg", "utf8"); const pathMap = { FooIcon: () => "http://localhost:3000/foo-icon.svg", BarIcon: () => "http://localhost:3000/bar-icon.svg", TitleDescriptionIcon: () => "http://localhost:3000/title-description-icon.svg", Play: () => "http://localhost:3000/play.svg", DataHref: () => "http://localhost:3000/datahref.svg", }; describe("Svg", () => { const { SVG } = (0, Svg_1.setup)(pathMap); function setup({ props = {}, } = {}) { const element = react_1.default.createElement(SVG, Object.assign({}, props)); const baseResult = (0, react_2.render)(element); const cloneElement = (props) => react_1.default.cloneElement(element, props); const rerender = (props) => baseResult.rerender(cloneElement(props)); const { root, result } = createResult(baseResult); return { root, result: Object.assign(Object.assign({}, result), { rerender }) }; } beforeEach(() => { jest.useFakeTimers(); Svg_1.ForTest["state"].setupCompleted = false; Svg_1.ForTest["state"].cacheObject = {}; Svg_1.ForTest["state"].updateQueueObject = {}; Svg_1.ForTest["state"].aggregation = { start: { queue: [] }, fetch: { queue: [] }, render: { queue: [] }, }; fetchMockIf({ "/foo-icon.svg": fooIcon, "/bar-icon.svg": barIcon, "/title-description-icon.svg": titleDescriptionIcon, "/play.svg": playSvg, "/datahref.svg": datahrefSvg, }); }); describe("初期状態", () => { it("スケルトンが表示されること", () => { const { root } = setup(); const element = root.query(); expect_initial(element); expect(element).toMatchSnapshot(); }); }); describe("ローディング中", () => { it("読み込み中になること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup(); const element = root.query(); emit(element, "FooIcon"); expect_loading(element, "FooIcon"); expect(element).toMatchSnapshot(); })); }); describe("fetch中", () => { it("読み込み中になること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup(); const element = root.query(); yield emitFetch(element, "FooIcon"); expect_loading(element, "FooIcon"); expect(element).toMatchSnapshot(); })); it("A->Bと更新するときも読み込み中になること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({}); const element = root.query(); yield change(element, "FooIcon"); yield emitFetch(element, "BarIcon"); expect_loading(element, "BarIcon"); expect(element).toMatchSnapshot(); })); }); describe("読み込み完了時", () => { it("FooIconに更新できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({}); const element = root.query(); yield change(element, "FooIcon"); expect_complete(element, "FooIcon"); expect(element).toMatchSnapshot(); })); it("A->Bと更新できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({}); const element = root.query(); yield change(element, "FooIcon"); yield change(element, "BarIcon"); expect_complete(element, "BarIcon"); expect(element).toMatchSnapshot(); })); it("A->B->Aに更新できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({}); const element = root.query(); yield change(element, "FooIcon"); yield change(element, "BarIcon"); yield change(element, "FooIcon"); expect_complete(element, "FooIcon"); expect(element).toMatchSnapshot(); })); }); describe("特殊なSVGの指定", () => { it("svg_NULL のイベントを発生させるとSVGが切り替わること", () => { const { root } = setup(); const element = root.query(); emit(element, "NULL"); // NULLはemitだけで反映される expect(element).not.toBeInTheDocument(); expect(element).toMatchSnapshot(); }); it.each(["NONE", "HIDDEN"])("svg_%s のイベントを発生させるとSVGが切り替わること", (svgName) => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup(); const element = root.query(); emit(element, svgName); // NONE HIDDENはDOMの更新を待つ必要がある yield waitForDomUpdate(); expect_complete(element, svgName); expect(element).toMatchSnapshot(); })); }); describe("props", () => { describe("defaultName指定時", () => { it("NULLのときは要素を表示しないこと", () => { const { root } = setup({ props: { defaultName: "NULL" } }); const element = root.query(); // defaultNameのNULLは初回の描画から反映される expect(element).not.toBeInTheDocument(); expect(element).toMatchSnapshot(); }); it.each(["NONE", "HIDDEN"])("%s のときは不可視要素を表示すること", (svgName) => { const { root } = setup({ props: { defaultName: svgName } }); const element = root.query(); // defaultNameのNONE HIDDENは初回の描画から反映される expect_complete(element, svgName); expect(element).toMatchSnapshot(); }); it("animationstartを経由せずに可視要素を表示すること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ props: { defaultName: "FooIcon" } }); const element = root.query(); expect_loading(element, "FooIcon"); yield waitForAnimationStart(); yield waitForDomUpdate(); expect_complete(element, "FooIcon"); expect(element).toMatchSnapshot(); })); }); describe("title", () => { it("titleを指定できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ props: { title: "newTitle" } }); const element = root.query(); expect(react_2.screen.queryByTitle("newTitle")).not.toBeInTheDocument(); yield change(element, "FooIcon"); expect(react_2.screen.queryByTitle("newTitle")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it("既存のtitleを上書きできること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ props: { title: "newTitle" } }); const element = root.query(); expect(react_2.screen.queryByTitle("newTitle")).not.toBeInTheDocument(); yield change(element, "TitleDescriptionIcon"); expect(react_2.screen.queryByTitle("newTitle")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it("後からtitleを更新できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root, result } = setup({}); const element = root.query(); yield change(element, "FooIcon"); expect(react_2.screen.queryByTitle("updateTitle")).not.toBeInTheDocument(); result.rerender({ title: "updateTitle" }); expect(react_2.screen.queryByTitle("updateTitle")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it.each(["HIDDEN", "NONE", "NULL"])("SVGが %s の場合はtitleが無視されること", (svgName) => __awaiter(void 0, void 0, void 0, function* () { const { root, result } = setup({ props: { title: "newTitle" } }); const element = root.query(); yield change(element, svgName); expect(react_2.screen.queryByTitle("newTitle")).not.toBeInTheDocument(); result.rerender({ title: "updateTitle" }); expect(react_2.screen.queryByTitle("updateTitle")).not.toBeInTheDocument(); expect(element).toMatchSnapshot(); })); }); describe("description", () => { it("descriptionを指定できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ props: { description: "newDescription" } }); const element = root.query(); expect(react_2.screen.queryByText("newDescription")).not.toBeInTheDocument(); yield change(element, "FooIcon"); expect(react_2.screen.queryByText("newDescription")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it("既存のdescriptionを上書きできること", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ props: { description: "newDescription" } }); const element = root.query(); expect(react_2.screen.queryByText("newDescription")).not.toBeInTheDocument(); yield change(element, "TitleDescriptionIcon"); expect(react_2.screen.queryByText("newDescription")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it("後からdescriptionを更新できること", () => __awaiter(void 0, void 0, void 0, function* () { const { root, result } = setup({}); const element = root.query(); yield change(element, "FooIcon"); expect(react_2.screen.queryByTitle("updateDescription")).not.toBeInTheDocument(); result.rerender({ title: "updateDescription" }); expect(react_2.screen.queryByTitle("updateDescription")).toBeInTheDocument(); expect(element).toMatchSnapshot(); })); it.each(["HIDDEN", "NONE", "NULL"])("SVGが %s の場合はdescription無視されること", (svgName) => __awaiter(void 0, void 0, void 0, function* () { const { root, result } = setup({ props: { description: "newDescription" }, }); const element = root.query(); yield change(element, svgName); expect(react_2.screen.queryByTitle("newDescription")).not.toBeInTheDocument(); result.rerender({ description: "updateTitle" }); expect(react_2.screen.queryByTitle("updateTitle")).not.toBeInTheDocument(); expect(element).toMatchSnapshot(); })); }); describe("innerRef", () => { it("refで要素を得られること", () => { const innerRef = react_1.default.createRef(); setup({ props: { innerRef } }); expect(innerRef.current).toBeInstanceOf(SVGSVGElement); expect(innerRef.current).toMatchSnapshot(); }); }); describe("onLoad", () => { it("初期状態では呼び出されていないこと", () => { const fn = jest.fn(); setup({ props: { onLoad: fn } }); expect(fn).toBeCalledTimes(0); }); it("SVG読み込み完了時に呼び出されること", () => __awaiter(void 0, void 0, void 0, function* () { const fn = jest.fn(); const { root } = setup({ props: { onLoad: fn } }); const element = root.query(); emit(element, "FooIcon"); expect(fn).toBeCalledTimes(0); yield waitForAnimationStart(); expect(fn).toBeCalledTimes(0); yield waitForDomUpdate(); expect(fn).toBeCalledTimes(1); expect(fn.mock.calls[0][0]).toBe(pathMap.FooIcon()); expect(fn.mock.calls[0][1]).toBe(false); emit(element, "BarIcon"); expect(fn).toBeCalledTimes(1); yield waitForAnimationStart(); expect(fn).toBeCalledTimes(1); yield waitForDomUpdate(); expect(fn).toBeCalledTimes(2); expect(fn.mock.calls[1][0]).toBe(pathMap.BarIcon()); expect(fn.mock.calls[1][1]).toBe(false); yield change(element, "FooIcon"); expect(fn).toBeCalledTimes(3); expect(fn.mock.calls[2][0]).toBe(pathMap.FooIcon()); expect(fn.mock.calls[2][1]).toBe(true); })); }); describe("onError", () => { it("初期状態では呼び出されていないこと", () => { const fn = jest.fn(); setup({ props: { onError: fn } }); expect(fn).toBeCalledTimes(0); }); it("未定義のアニメーション名でonErrorが発生すること", () => { const fn = jest.fn(); const { root } = setup({ props: { onError: fn } }); const element = root.query(); emit(element, "ThrowError"); expect(fn).toBeCalledTimes(1); expect(fn.mock.calls[0][0]).toBeInstanceOf(TypeError); expect(fn.mock.calls[0][0].message).toBe(`unknown svgName "ThrowError"`); expect(element).toMatchSnapshot(); }); }); }); describe("setupSvg", () => { describe("uniquifyIDs", () => { function setup({ defaultName, uniqueHash, }) { const { SVG } = (0, Svg_1.setup)(pathMap, { uniquifyIDs: true, uniqueHash }); return createResult((0, react_2.render)(react_1.default.createElement("div", null, react_1.default.createElement(SVG, { "data-testid": "svg1", defaultName: defaultName }), react_1.default.createElement(SVG, { "data-testid": "svg2" })))); } it("should uniquify ids with the random uniqueHash", () => __awaiter(void 0, void 0, void 0, function* () { var _a, _b; const { root } = setup({ defaultName: "Play" }); const svg1 = react_2.screen.getByTestId("svg1"); const svg2 = react_2.screen.getByTestId("svg2"); yield waitForFetch(); yield waitForDomUpdate(); yield change(svg2, "Play"); expect((_a = svg1.querySelector("radialGradient")) === null || _a === void 0 ? void 0 : _a.id).toEqual(expect.stringMatching(/^radialGradient-1__[\dA-Za-z]{8}$/)); expect((_b = svg2.querySelector("radialGradient")) === null || _b === void 0 ? void 0 : _b.id).toEqual(expect.stringMatching(/^radialGradient-1__[\dA-Za-z]{8}$/)); })); it("should uniquify ids with a custom uniqueHash", () => __awaiter(void 0, void 0, void 0, function* () { var _c, _d; const { root } = setup({ defaultName: "Play", uniqueHash: "test" }); const svg1 = react_2.screen.getByTestId("svg1"); const svg2 = react_2.screen.getByTestId("svg2"); yield waitForFetch(); yield waitForDomUpdate(); yield change(svg2, "Play"); expect((_c = svg1.querySelector("radialGradient")) === null || _c === void 0 ? void 0 : _c.id).toEqual(expect.stringMatching(/^radialGradient-1__test$/)); expect((_d = svg2.querySelector("radialGradient")) === null || _d === void 0 ? void 0 : _d.id).toEqual(expect.stringMatching(/^radialGradient-1__test$/)); expect(root.get()).toMatchSnapshot(); })); it("should not uniquify non-id hrefs", () => __awaiter(void 0, void 0, void 0, function* () { const { root } = setup({ defaultName: "DataHref", uniqueHash: "test" }); const svg2 = react_2.screen.getByTestId("svg2"); yield waitForFetch(); yield waitForDomUpdate(); yield change(svg2, "DataHref"); expect(root.get()).toMatchSnapshot(); })); }); }); describe("全体処理", () => { function fillMap(length, make) { return Array.from({ length }) .map((_, i) => i) .reduce((map, i) => { const [key, value] = make(i); map[key] = value; return map; }, {}); } function summary(element) { return { // A: aria-busy="true" A: element.querySelectorAll("svg[aria-busy=true]:not([data-svg-status])").length, // B: aria-busy="true" data-svg-status="loading" B: element.querySelectorAll("svg[aria-busy=true][data-svg-status=loading]:not([data-svg-name])").length, // C: aria-busy="true" data-svg-name="*" data-svg-status="loading" C: element.querySelectorAll("svg[aria-busy=true][data-svg-status=loading][data-svg-name]").length, // D: data-svg-name="*" data-svg-status="complete" D: element.querySelectorAll("svg[data-svg-status=complete][data-svg-name]").length, }; } function svgTag(index) { return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${index} ${index}"><title>${index}</title></svg>`; } describe("10種類10個ずつ100個表示の場合", () => { beforeEach(() => { fetchMockIf(fillMap(10, (i) => [`/${i}.svg`, svgTag(i)])); }); describe("defaultName指定時", () => { function setup() { const { SVG } = (0, Svg_1.setup)(fillMap(10, (i) => [i, () => `http://localhost:3000/${i}.svg`])); return createResult((0, react_2.render)(react_1.default.createElement("div", null, Array.from({ length: 100 }).map((_, i) => (react_1.default.createElement(SVG, { key: i, defaultName: String(i % 10) })))))); } it("初期描画後", () => { const element = setup().root.get(); expect(element).toMatchSnapshot(); }); it("徐々に変化していくこと", () => __awaiter(void 0, void 0, void 0, function* () { const element = setup().root.get(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 100, D: 0 }); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 100, D: 0 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 68, D: 32 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 36, D: 64 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 4, D: 96 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 0, D: 100 }); expect(element).toMatchSnapshot(); })); }); describe("defaultName指定なし", () => { function setup() { const { SVG } = (0, Svg_1.setup)(fillMap(10, (i) => [i, () => `http://localhost:3000/${i}.svg`])); return createResult((0, react_2.render)(react_1.default.createElement("div", null, Array.from({ length: 100 }).map((_, i) => (react_1.default.createElement(SVG, { key: i })))))); } it("初期描画後", () => { const element = setup().root.get(); expect(element).toMatchSnapshot(); }); it("徐々に変化していくこと", () => __awaiter(void 0, void 0, void 0, function* () { const element = setup().root.get(); expect(summary(element)).toStrictEqual({ A: 100, B: 0, C: 0, D: 0 }); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 84, B: 16, C: 0, D: 0 }); fireAnimationstart(element); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 84, B: 0, C: 16, D: 0 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 68, B: 16, C: 0, D: 16 }); fireAnimationstart(element); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 68, B: 16, C: 0, D: 16 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 52, B: 16, C: 0, D: 32 }); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 52, B: 16, C: 0, D: 32 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 36, B: 32, C: 0, D: 32 }); fireAnimationstart(element); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 36, B: 32, C: 0, D: 32 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 20, B: 16, C: 0, D: 64 }); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 20, B: 16, C: 0, D: 64 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 4, B: 32, C: 0, D: 64 }); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 4, B: 32, C: 0, D: 64 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 36, C: 0, D: 64 }); fireAnimationstart(element); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 0, B: 36, C: 0, D: 64 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 4, C: 0, D: 96 }); fireAnimationstart(element); yield waitForAnimationStart(); expect(summary(element)).toStrictEqual({ A: 0, B: 4, C: 0, D: 96 }); yield waitForDomUpdate(); expect(summary(element)).toStrictEqual({ A: 0, B: 0, C: 0, D: 100 }); expect(element).toMatchSnapshot(); })); }); }); }); }); function createResult(result) { return { result, root: { query: () => result.container.firstElementChild, get: () => { if (result.container.firstElementChild) { return result.container.firstElementChild; } throw new Error("element not exists"); }, }, }; } function fireAnimationstart(element) { const svgList = Array.from(element.querySelectorAll("svg")); (0, react_2.act)(() => { element.querySelectorAll("svg[data-svg-status=loading]").forEach((svg) => { const pos = svgList.findIndex((s) => s === svg); react_2.fireEvent.animationStart(svg, { animationName: `svg_${pos % 10}` }); }); }); } function emit(element, svgName) { (0, react_2.act)(() => { element && react_2.fireEvent.animationStart(element, { animationName: `svg_${svgName}` }); }); } function emitFetch(element, svgName) { return __awaiter(this, void 0, void 0, function* () { emit(element, svgName); yield waitForAnimationStart(); }); } function change(element, svgName) { return __awaiter(this, void 0, void 0, function* () { yield emitFetch(element, svgName); yield waitForDomUpdate(); }); } function waitForFetch() { return __awaiter(this, void 0, void 0, function* () { yield (0, react_2.waitFor)(() => { jest.advanceTimersByTime(0); }); }); } function waitForDomUpdate() { return __awaiter(this, void 0, void 0, function* () { yield (0, react_2.waitFor)(() => { jest.advanceTimersByTime(16); }); }); } // NOTE: React18からwaitForFetchを3回呼ばないとanimationstartがハンドリングできない function waitForAnimationStart() { return __awaiter(this, void 0, void 0, function* () { yield waitForFetch(); yield waitForFetch(); yield waitForFetch(); }); } function expect_initial(element) { expect(element).toHaveAttribute("aria-busy", "true"); expect(element).not.toHaveAttribute("data-svg-name"); expect(element).not.toHaveAttribute("data-svg-status"); } function expect_loading(element, svgName) { expect(element).toHaveAttribute("aria-busy", "true"); expect(element).toHaveAttribute("data-svg-name", svgName); expect(element).toHaveAttribute("data-svg-status", "loading"); } function expect_complete(element, svgName) { expect(element).not.toHaveAttribute("aria-busy"); expect(element).toHaveAttribute("data-svg-name", svgName); expect(element).toHaveAttribute("data-svg-status", "complete"); } // jestにAnimationEventが存在しないのでmockを追加 // https://gitanswer.com/fireevent-animationend-with-animationname-event-animationname-is-undefined-javascript-react-testing-library-842276564 global.AnimationEvent = class AnimationEvent extends Event { constructor(type, animationEventInitDict = {}) { const { animationName = "", elapsedTime = 0, pseudoElement = "" } = animationEventInitDict, eventInitDict = __rest(animationEventInitDict, ["animationName", "elapsedTime", "pseudoElement"]); super(type, eventInitDict); this._animationName = animationName; this._elapsedTime = elapsedTime; this._pseudoElement = pseudoElement; } get animationName() { return this._animationName; } get elapsedTime() { return this._elapsedTime; } get pseudoElement() { return this._pseudoElement; } }; function fetchMockIf(patterns) { jest_fetch_mock_1.default.mockIf(/^http:\/\/localhost:3000\/.*$/, (req) => __awaiter(this, void 0, void 0, function* () { const key = Object.keys(patterns).find((key) => req.url.endsWith(key)); if (key) { return patterns[key]; } else { return { status: 404, body: "Not Found", }; } })); }