mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
### What does this PR do? Fixes #22014 todo: - [x] not spawn sync - [x] better comm to subprocess (not stderr) - [x] tty - [x] more tests (also include some tests for the actual implementation of a provider) - [x] disable autoinstall? Scanner template: https://github.com/oven-sh/security-scanner-template <!-- **Please explain what your changes do**, example: --> <!-- This adds a new flag --bail to bun test. When set, it will stop running tests after the first failure. This is useful for CI environments where you want to fail fast. --> --- - [x] Documentation or TypeScript types (it's okay to leave the rest blank in this case) - [x] Code changes ### How did you verify your code works? <!-- **For code changes, please include automated tests**. Feel free to uncomment the line below --> <!-- I wrote automated tests --> <!-- If JavaScript/TypeScript modules or builtins changed: - [ ] I included a test for the new code, or existing tests cover it - [ ] I ran my tests locally and they pass (`bun-debug test test-file-name.test`) --> <!-- If Zig files changed: - [ ] I checked the lifetime of memory allocated to verify it's (1) freed and (2) only freed when it should be - [ ] I included a test for the new code, or an existing test covers it - [ ] JSValue used outside of the stack is either wrapped in a JSC.Strong or is JSValueProtect'ed - [ ] I wrote TypeScript/JavaScript tests and they pass locally (`bun-debug test test-file-name.test`) --> <!-- If new methods, getters, or setters were added to a publicly exposed class: - [ ] I added TypeScript types for the new methods, getters, or setters --> <!-- If dependencies in tests changed: - [ ] I made sure that specific versions of dependencies are used instead of ranged or tagged versions --> <!-- If a new builtin ESM/CJS module was added: - [ ] I updated Aliases in `module_loader.zig` to include the new module - [ ] I added a test that imports the module - [ ] I added a test that require() the module --> tests (bad currently) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Dylan Conway <dylan-conway@users.noreply.github.com> Co-authored-by: Dylan Conway <dylan.conway567@gmail.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
171 lines
4.2 KiB
TypeScript
171 lines
4.2 KiB
TypeScript
/**
|
|
* This file can be directly run
|
|
*
|
|
* PACKAGE_DIR_TO_USE=(realpath .) bun test/cli/install/dummy.registry.ts
|
|
*/
|
|
import { file, Server } from "bun";
|
|
import { tmpdirSync } from "harness";
|
|
|
|
let expect: (typeof import("bun:test"))["expect"];
|
|
|
|
import { writeFile } from "fs/promises";
|
|
import { basename, join } from "path";
|
|
|
|
type Handler = (req: Request) => Response | Promise<Response>;
|
|
type Pkg = {
|
|
name: string;
|
|
version: string;
|
|
dist: {
|
|
tarball: string;
|
|
};
|
|
};
|
|
let handler: Handler;
|
|
let server: Server;
|
|
export let package_dir: string;
|
|
export let requested: number;
|
|
export let root_url: string;
|
|
export let check_npm_auth_type = { check: true };
|
|
|
|
export async function write(path: string, content: string | object) {
|
|
if (!package_dir) throw new Error("writeToPackageDir() must be called in a test");
|
|
|
|
await Bun.write(join(package_dir, path), typeof content === "string" ? content : JSON.stringify(content));
|
|
}
|
|
|
|
export function read(path: string) {
|
|
return Bun.file(join(package_dir, path));
|
|
}
|
|
|
|
export function dummyRegistry(urls: string[], info: any = { "0.0.2": {} }, numberOfTimesTo500PerURL = 0) {
|
|
let retryCountsByURL = new Map<string, number>();
|
|
const _handler: Handler = async request => {
|
|
urls.push(request.url);
|
|
const url = request.url.replaceAll("%2f", "/");
|
|
|
|
let status = 200;
|
|
|
|
if (numberOfTimesTo500PerURL > 0) {
|
|
let currentCount = retryCountsByURL.get(request.url);
|
|
if (currentCount === undefined) {
|
|
retryCountsByURL.set(request.url, numberOfTimesTo500PerURL);
|
|
status = 500;
|
|
} else {
|
|
retryCountsByURL.set(request.url, currentCount - 1);
|
|
status = currentCount > 0 ? 500 : 200;
|
|
}
|
|
}
|
|
|
|
expect(request.method).toBe("GET");
|
|
if (url.endsWith(".tgz")) {
|
|
return new Response(file(join(import.meta.dir, basename(url).toLowerCase())), { status });
|
|
}
|
|
expect(request.headers.get("accept")).toBe(
|
|
"application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*",
|
|
);
|
|
if (check_npm_auth_type.check) {
|
|
expect(request.headers.get("npm-auth-type")).toBe(null);
|
|
}
|
|
expect(await request.text()).toBe("");
|
|
|
|
const name = url.slice(url.indexOf("/", root_url.length) + 1);
|
|
const versions: Record<string, Pkg> = {};
|
|
let version;
|
|
for (version in info) {
|
|
if (!/^[0-9]/.test(version)) continue;
|
|
versions[version] = {
|
|
name,
|
|
version,
|
|
dist: {
|
|
tarball: `${url}-${info[version].as ?? version}.tgz`,
|
|
},
|
|
...info[version],
|
|
};
|
|
}
|
|
|
|
return new Response(
|
|
JSON.stringify({
|
|
name,
|
|
versions,
|
|
"dist-tags": {
|
|
latest: info.latest ?? version,
|
|
},
|
|
}),
|
|
{ status },
|
|
);
|
|
};
|
|
return _handler;
|
|
}
|
|
|
|
export function setHandler(newHandler: Handler) {
|
|
handler = newHandler;
|
|
}
|
|
|
|
function resetHandler() {
|
|
setHandler(() => new Response("Tea Break~", { status: 418 }));
|
|
}
|
|
|
|
export function dummyBeforeAll() {
|
|
server = Bun.serve({
|
|
async fetch(request) {
|
|
requested++;
|
|
return await handler(request);
|
|
},
|
|
port: 0,
|
|
});
|
|
root_url = `http://localhost:${server.port}`;
|
|
}
|
|
|
|
export function dummyAfterAll() {
|
|
server.stop();
|
|
}
|
|
|
|
export function getPort() {
|
|
return server.port;
|
|
}
|
|
|
|
let packageDirGetter: () => string = () => {
|
|
return tmpdirSync();
|
|
};
|
|
export async function dummyBeforeEach() {
|
|
resetHandler();
|
|
requested = 0;
|
|
package_dir = packageDirGetter();
|
|
await writeFile(
|
|
join(package_dir, "bunfig.toml"),
|
|
`
|
|
[install]
|
|
cache = false
|
|
registry = "http://localhost:${server.port}/"
|
|
saveTextLockfile = false
|
|
`,
|
|
);
|
|
}
|
|
|
|
export async function dummyAfterEach() {
|
|
resetHandler();
|
|
}
|
|
|
|
if (Bun.main === import.meta.path) {
|
|
// @ts-expect-error
|
|
expect = value => {
|
|
return {
|
|
toBe(expected) {
|
|
if (value !== expected) {
|
|
throw new Error(`Expected ${value} to be ${expected}`);
|
|
}
|
|
},
|
|
};
|
|
};
|
|
if (process.env.PACKAGE_DIR_TO_USE) {
|
|
packageDirGetter = () => process.env.PACKAGE_DIR_TO_USE!;
|
|
}
|
|
|
|
await dummyBeforeAll();
|
|
await dummyBeforeEach();
|
|
setHandler(dummyRegistry([]));
|
|
console.log("Running dummy registry!\n\n URL: ", root_url!, "\n", "DIR: ", package_dir!);
|
|
} else {
|
|
// @ts-expect-error
|
|
({ expect } = Bun.jest(import.meta.path));
|
|
}
|