UNPKG

webextension-store-meta

Version:

Get browser extension(webextension) item meta from Chrome Web Store, Firefox add-ons, and Microsoft Edge Add-ons.

149 lines (135 loc) 4.75 kB
import { fetch } from "undici"; import { describe, expect, it, type MockedFunction, vi } from "vitest"; import { fetchText } from "../../utils/fetch-text"; import { EdgeAddons } from ".."; import { fixtures } from "./fixtures"; const fetchTextMock = fetchText as MockedFunction<typeof fetchText>; vi.mock("../../utils/fetch-text", () => { const cache = new Map<string, string>(); return { fetchText: vi.fn(async (url, options) => { if (cache.has(url)) { return cache.get(url); } const result = await fetch(url, options).then((res) => res.text()); cache.set(url, result); return result; }), }; }); describe("Edge Add-ons", async () => { const matchAnyInfo = { availability: expect.any(Array), activeInstallCount: expect.any(Number), storeProductId: expect.any(String), name: expect.any(String), logoUrl: expect.stringMatching(/^https:\/\//), description: expect.any(String), developer: expect.any(String), category: expect.any(String), isInstalled: expect.any(Boolean), crxId: expect.any(String), manifest: expect.any(String), isHavingMatureContent: expect.any(Boolean), version: expect.any(String), lastUpdateDate: expect.any(Number), privacyUrl: expect.any(String), availabilityId: expect.any(String), skuId: expect.any(String), locale: expect.any(String), market: expect.any(String), averageRating: expect.any(Number), ratingCount: expect.any(Number), availableLanguages: expect.any(Array), metadata: expect.any(Object), shortDescription: expect.any(String), searchKeywords: expect.any(String), screenshots: expect.any(Array), videos: expect.any(Array), publisherWebsiteUri: expect.any(String), isBadgedAsFeatured: expect.any(Boolean), url: expect.stringMatching( /^https:\/\/microsoftedge\.microsoft\.com\/addons\/detail\//, ), }; describe.each(await fixtures())("%s", (id) => { it("should return ext info", async () => { const edgeAddons = new EdgeAddons({ id }); await edgeAddons.load(); expect(edgeAddons.meta()).toMatchObject({ ...matchAnyInfo, crxId: id, }); }); it("should also return ext info with static `load` shortcut", async () => { const edgeAddons = await EdgeAddons.load({ id }); expect(edgeAddons.meta()).toMatchObject({ ...matchAnyInfo, crxId: id, }); }); it("should concat querystring", async () => { const edgeAddons = await EdgeAddons.load({ id, qs: { hl: "zh", gl: "CN" }, }); expect(edgeAddons.meta()).toMatchObject({ ...matchAnyInfo, crxId: id, }); expect(fetchTextMock).toHaveBeenLastCalledWith( expect.stringContaining("?hl=zh&gl=CN"), undefined, ); }); it("should throw error if item is not loaded", () => { const edgeAddons = new EdgeAddons({ id }); expect(() => edgeAddons.meta()).toThrow(); }); }, 20000); it("should fall back to detail page metadata when JSON endpoint fails", async () => { fetchTextMock .mockRejectedValueOnce(new Error("JSON endpoint unavailable")) .mockResolvedValueOnce(` <!DOCTYPE html> <html> <head> <title>Fallback Extension - Microsoft Edge Add-ons</title> </head> <body> <div itemscope itemtype="http://schema.org/WebApplication"> <span itemprop="interactionStatistic" itemscope itemtype="http://schema.org/InteractionCounter"> <meta itemprop="userInteractionCount" content="1,234" /> </span> </div> <span itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating"> <meta itemprop="ratingValue" content="4.5" /> <meta itemprop="ratingCount" content="67" /> </span> </body> </html> `); const edgeAddons = await EdgeAddons.load({ id: "fallback-id" }); expect(edgeAddons.meta()).toMatchObject({ name: "Fallback Extension", activeInstallCount: 1234, averageRating: 4.5, ratingCount: 67, url: "https://microsoftedge.microsoft.com/addons/detail/fallback-id", }); }); it("should get null if extension is not found", async () => { fetchTextMock.mockRejectedValue(new Error("404 Not Found")); const edgeAddons = await EdgeAddons.load({ id: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", }); expect(edgeAddons.meta()).toMatchObject({ activeInstallCount: null, name: null, logoUrl: null, averageRating: null, ratingCount: null, url: null, }); }); });