84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import {
|
|
existsSync,
|
|
mkdtempSync,
|
|
readFileSync,
|
|
rmSync,
|
|
statSync,
|
|
} from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { downloadPrivateRom } from "../scripts/fetch-private-rom.mjs";
|
|
|
|
const directories: string[] = [];
|
|
const secret = "https://private.invalid/crystal?token=never-log-this";
|
|
function destination() {
|
|
const directory = mkdtempSync(join(tmpdir(), "crystal-download-"));
|
|
directories.push(directory);
|
|
return join(directory, "private", "crystal.gbc");
|
|
}
|
|
afterEach(() => {
|
|
for (const directory of directories.splice(0))
|
|
rmSync(directory, { recursive: true, force: true });
|
|
});
|
|
|
|
it("requires HTTPS before making a request", async () => {
|
|
const fetcher = vi.fn();
|
|
await expect(
|
|
downloadPrivateRom("http://private.invalid/game", destination(), fetcher),
|
|
).rejects.toThrow("HTTPS");
|
|
expect(fetcher).not.toHaveBeenCalled();
|
|
});
|
|
it("does not disclose the URL in network errors and refuses redirects", async () => {
|
|
const fetcher = vi
|
|
.fn()
|
|
.mockRejectedValue(new Error(`Cannot connect to ${secret}`));
|
|
const path = destination();
|
|
await expect(downloadPrivateRom(secret, path, fetcher)).rejects.toThrow(
|
|
/^Private ROM download failed\./,
|
|
);
|
|
expect(fetcher.mock.calls[0][1].redirect).toBe("error");
|
|
expect(existsSync(path)).toBe(false);
|
|
});
|
|
it("reports an IP restriction failure without saving the error page", async () => {
|
|
const path = destination();
|
|
await expect(
|
|
downloadPrivateRom(
|
|
secret,
|
|
path,
|
|
async () => new Response("Forbidden", { status: 403 }),
|
|
),
|
|
).rejects.toThrow("HTTP 403");
|
|
expect(existsSync(path)).toBe(false);
|
|
});
|
|
it.each([100, 2 * 1024 * 1024, 2 * 1024 * 1024 + 1])(
|
|
"refuses invalid ROM content of %i bytes",
|
|
async (size) => {
|
|
const path = destination();
|
|
await expect(
|
|
downloadPrivateRom(
|
|
secret,
|
|
path,
|
|
async () => new Response(new Uint8Array(size)),
|
|
),
|
|
).rejects.toThrow();
|
|
expect(existsSync(path)).toBe(false);
|
|
},
|
|
);
|
|
|
|
const romPath =
|
|
process.env.CRYSTAL_ROM_PATH ??
|
|
"Pokemon - Crystal Version (UE) (V1.1) [C][!].gbc";
|
|
describe.skipIf(!existsSync(romPath))("verified private download", () => {
|
|
it("writes the exact verified bytes privately and refuses to overwrite an existing file", async () => {
|
|
const path = destination();
|
|
const rom = readFileSync(romPath);
|
|
const fetcher = async () => new Response(rom);
|
|
await downloadPrivateRom(secret, path, fetcher);
|
|
expect(readFileSync(path).equals(rom)).toBe(true);
|
|
expect(statSync(path).mode & 0o777).toBe(0o600);
|
|
await expect(downloadPrivateRom(secret, path, fetcher)).rejects.toThrow();
|
|
expect(readFileSync(path).equals(rom)).toBe(true);
|
|
});
|
|
});
|