Ctrl K
ComunidadGuías…

packages/app/vite.icons.test.ts

Rama dev · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { expect, test } from "bun:test"
import { fetch } from "bun"
import { build, createServer } from "vite"
import { icons } from "./vite.icons"
import manifest from "./manifest.json" with { type: "json" }

test.each(["dev", "beta", "prod", "local"])("bundles %s app icons", async (channel) => {
  const result = await build({
    root: import.meta.dirname,
    configFile: false,
    logLevel: "silent",
    plugins: [
      icons(channel),
      {
        name: "icons-only-fixture",
        transformIndexHtml: {
          order: "pre",
          handler: (html) => html.replace(/<script\b[^>]*>[\s\S]*?<\/script>/g, ""),
        },
      },
    ],
    build: { write: false, copyPublicDir: false },
  })

  if (!("output" in result)) throw new Error("Expected a single build output")

  await check(channel === "local" ? "dev" : channel, async (path) => {
    const file = result.output.find((file) => `/${file.fileName}` === path)

    if (file?.type !== "asset") throw new Error(`Missing asset: ${path}`)

    return new Uint8Array(Buffer.from(file.source))
  })
})

test.each(["dev", "beta", "prod"])("serves %s app icons", async (channel) => {
  const server = await createServer({
    root: import.meta.dirname,
    configFile: false,
    logLevel: "silent",
    plugins: [icons(channel)],
    optimizeDeps: { noDiscovery: true, include: [] },
    server: { host: "127.0.0.1", port: 0, hmr: false, preTransformRequests: false, watch: null },
  })

  try {
    await server.listen()
    const url = server.resolvedUrls?.local[0]

    if (!url) throw new Error("Expected a local URL")

    await check(channel, async (path) => {
      const response = await fetch(new URL(path, url))
      expect(response.status).toBe(200)

      if (path.endsWith(".webmanifest")) expect(response.headers.get("content-type")).toBe("application/manifest+json")

      if (path.endsWith(".png")) expect(response.headers.get("content-type")).toBe("image/png")

      return new Uint8Array(await response.arrayBuffer())
    })
  } finally {
    await server.close()
  }
})

async function check(channel: string, read: (path: string) => Promise<Uint8Array>) {
  const html = new TextDecoder().decode(await read("/index.html"))
  const actual: typeof manifest = JSON.parse(new TextDecoder().decode(await read("/site.webmanifest")))
  expect(actual.icons.some((icon) => icon.purpose === "maskable")).toBe(true)
  expect(actual).toEqual({
    ...manifest,
    icons: manifest.icons.map((icon) => ({ ...icon, src: `/icons/${channel}${icon.src}` })),
  })
  expect(html).toContain(`href="/icons/${channel}/favicon.ico"`)
  expect(html).toContain(`href="/icons/${channel}/apple-touch-icon.png"`)
  expect(html).toContain(`href="/site.webmanifest"`)
  expect(html).not.toContain("%OPENCODE_")

  await Promise.all(
    Object.entries({
      "favicon.ico": "icon.ico",
      "apple-touch-icon.png": "ios/AppIcon-60x60@3x.png",
      "web-app-manifest-192x192.png": "android/mipmap-xxxhdpi/ic_launcher.png",
      "web-app-manifest-512x512.png": "icon.png",
    }).map(async ([name, source]) => {
      const bytes = await read(`/icons/${channel}/${name}`)
      expect(bytes).toEqual(await Bun.file(new URL(`../desktop/icons/${channel}/${source}`, import.meta.url)).bytes())

      if (!name.endsWith(".png")) return
      const size = name === "apple-touch-icon.png" ? 180 : Number(name.match(/(192|512)/)?.[0])
      expect(new DataView(bytes.buffer, bytes.byteOffset).getUint32(16)).toBe(size)
      expect(new DataView(bytes.buffer, bytes.byteOffset).getUint32(20)).toBe(size)
    }),
  )
}