Files
pikasTech-unidesk/scripts/src/provider-apps.test.ts
T
pikastech 5fee59448c
Pipelines as Code CI / hwlab-web-probe-sentinel-nc01- Success
Pipelines as Code CI / platform-infra-gitea-nc01- Failed
Pipelines as Code CI / unidesk-host- Success
fix(provider-apps): 发布同源品牌图标
2026-07-19 16:57:31 +02:00

109 lines
4.9 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { resolve } from "node:path";
import { readProviderAppsConfig } from "../../src/components/provider-apps/config";
import { readProviderRelease, releaseResponse } from "../../src/components/provider-apps/release";
import { providerAppsHelp } from "./provider-apps";
const repositoryRoot = resolve(import.meta.dir, "../..");
describe("Provider Apps L1 release", () => {
const config = readProviderAppsConfig(repositoryRoot);
const release = readProviderRelease(repositoryRoot, config);
test("owning YAML declares a fixed native HTTPS origin", () => {
expect(config.target.id).toBe("NC01");
expect(config.runtime.port).toBe(18121);
expect(config.publicExposure.publicBaseUrl).toBe("https://apps.hwpod.com");
});
test("serves release files and rejects unknown or mutating requests", async () => {
expect((await releaseResponse("GET", config.release.routes.health, config, release).json()).ok).toBe(true);
expect(releaseResponse("GET", config.release.routes.manifest, config, release).status).toBe(200);
expect(releaseResponse("HEAD", config.release.routes.provider, config, release).status).toBe(200);
expect(releaseResponse("GET", "/private", config, release).status).toBe(404);
expect(releaseResponse("POST", config.release.routes.provider, config, release).status).toBe(405);
});
test("serves human and agent installer surfaces from one L1 service", async () => {
const index = releaseResponse(
"GET",
config.install.routes.index,
config,
release,
"https://apps.hwpod.com",
);
expect(index.status).toBe(200);
expect(index.headers.get("content-security-policy")).toContain("default-src 'self'");
const indexHtml = await index.text();
expect(indexHtml).toContain("32 条 TCP warm channel");
expect(indexHtml).toContain('<link rel="icon" href="/assets/provider-icon.svg"');
const appScript = await releaseResponse(
"GET",
config.install.routes.script,
config,
release,
).text();
const referencedIds = [...appScript.matchAll(/querySelector\("#([^"]+)"\)/gu)]
.map((match) => match[1]);
expect(referencedIds.length).toBeGreaterThan(0);
for (const id of referencedIds) {
expect(indexHtml).toContain(`id="${id}"`);
}
const contract = await releaseResponse(
"GET",
config.install.routes.contract,
config,
release,
"https://apps.hwpod.com",
).json() as Record<string, any>;
expect(contract.schemaVersion).toBe(2);
expect(contract.humanUrl).toBe("https://apps.hwpod.com/");
expect(contract.sensitiveInputs.acceptedByWeb).toBe(false);
expect(contract.installer.acceptsArguments).toBe(false);
expect(contract.config.mustExistBeforeInstall).toBe(true);
expect(contract.oneLineTemplate).toBe(
"irm 'https://apps.hwpod.com/v1/unideskcprovider/install.ps1' | iex",
);
const fallbackContract = await releaseResponse(
"GET",
config.install.routes.contract,
config,
release,
"http://127.0.0.1:18121",
).json() as Record<string, any>;
expect(fallbackContract.humanUrl).toBe("https://apps.hwpod.com/");
});
test("PowerShell installer has release URLs resolved and accepts no arguments", async () => {
const installer = await releaseResponse(
"GET",
config.install.routes.installer,
config,
release,
).text();
expect(installer).toContain("https://apps.hwpod.com/v1/unideskcprovider/update.json");
expect(installer).toContain("https://apps.hwpod.com/v1/unideskcprovider/unideskcprovider.py");
expect(installer).toContain("$ErrorActionPreference = \"Continue\"");
expect(installer).toContain("sys.modules[spec.name] = module");
expect(installer).toContain("\"config-probe-$PID.py\"");
expect(installer).not.toContain("\"-c\",\n $configProbeCode");
expect(installer).toContain("\"$providerPath.install.bak\"");
expect(installer).not.toContain("$providerPath, $null");
expect(installer).toContain("param()");
expect(installer).not.toContain("__MANIFEST_URL__");
expect(installer).not.toContain("__PROVIDER_URL__");
expect(installer).not.toContain("[Parameter(Mandatory");
expect(installer).not.toContain("nodeRequired");
expect(releaseResponse("HEAD", config.install.routes.style, config, release).status).toBe(200);
expect(releaseResponse("HEAD", config.install.routes.script, config, release).status).toBe(200);
expect(releaseResponse("HEAD", config.install.routes.favicon, config, release).status).toBe(200);
expect(releaseResponse("HEAD", config.install.routes.panelImage, config, release).status).toBe(200);
});
test("CLI help keeps one YAML-owned native lifecycle", () => {
const help = providerAppsHelp();
expect(help.config).toBe("config/platform-infra/apps.yaml");
expect(help.usage).toContain("bun scripts/cli.ts provider-apps server status");
});
});