70bf21e064
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
738 lines
20 KiB
TypeScript
738 lines
20 KiB
TypeScript
import { describe, it } from "vitest";
|
|
import {
|
|
extractBareImports,
|
|
getAllDependencies,
|
|
getEntryPointPaths,
|
|
getNonWorkspaceDependencies,
|
|
getPackageNameFromSpecifier,
|
|
getPublicPackages,
|
|
isBareSpecifier,
|
|
validateDistImports,
|
|
validatePackageDependencies,
|
|
} from "../validate-package-dependencies";
|
|
|
|
describe("getAllDependencies()", () => {
|
|
it("should return empty array for undefined", ({ expect }) => {
|
|
expect(getAllDependencies(undefined)).toEqual([]);
|
|
});
|
|
|
|
it("should return empty array for empty object", ({ expect }) => {
|
|
expect(getAllDependencies({})).toEqual([]);
|
|
});
|
|
|
|
it("should return all dependency names", ({ expect }) => {
|
|
expect(
|
|
getAllDependencies({
|
|
foo: "1.0.0",
|
|
bar: "workspace:*",
|
|
baz: "^2.0.0",
|
|
})
|
|
).toEqual(["foo", "bar", "baz"]);
|
|
});
|
|
});
|
|
|
|
describe("getNonWorkspaceDependencies()", () => {
|
|
it("should return empty array for undefined", ({ expect }) => {
|
|
expect(getNonWorkspaceDependencies(undefined)).toEqual([]);
|
|
});
|
|
|
|
it("should return empty array for empty object", ({ expect }) => {
|
|
expect(getNonWorkspaceDependencies({})).toEqual([]);
|
|
});
|
|
|
|
it("should filter out workspace dependencies", ({ expect }) => {
|
|
expect(
|
|
getNonWorkspaceDependencies({
|
|
foo: "1.0.0",
|
|
bar: "workspace:*",
|
|
baz: "workspace:^",
|
|
qux: "^2.0.0",
|
|
})
|
|
).toEqual(["foo", "qux"]);
|
|
});
|
|
|
|
it("should return all deps if none are workspace deps", ({ expect }) => {
|
|
expect(
|
|
getNonWorkspaceDependencies({
|
|
foo: "1.0.0",
|
|
bar: "^2.0.0",
|
|
})
|
|
).toEqual(["foo", "bar"]);
|
|
});
|
|
});
|
|
|
|
describe("validatePackageDependencies()", () => {
|
|
it("should return no errors for package with no dependencies", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{ name: "test-package" },
|
|
null
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should return no errors for package with only workspace dependencies", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
"@cloudflare/foo": "workspace:*",
|
|
"@cloudflare/bar": "workspace:^",
|
|
},
|
|
},
|
|
null
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should return error when package has non-workspace deps but no allowlist", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
zod: "^3.0.0",
|
|
},
|
|
},
|
|
null
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('Package "test-package"');
|
|
expect(errors[0]).toContain("2 non-workspace dependencies");
|
|
expect(errors[0]).toContain("no scripts/deps.ts file");
|
|
expect(errors[0]).toContain("lodash, zod");
|
|
});
|
|
|
|
it("should return no errors when all deps are in allowlist", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
zod: "^3.0.0",
|
|
},
|
|
},
|
|
["lodash", "zod"]
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should return error for dependency not in allowlist", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
zod: "^3.0.0",
|
|
"new-dep": "^1.0.0",
|
|
},
|
|
},
|
|
["lodash", "zod"]
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('Package "test-package"');
|
|
expect(errors[0]).toContain('"new-dep"');
|
|
expect(errors[0]).toContain("not listed in EXTERNAL_DEPENDENCIES");
|
|
});
|
|
|
|
it("should return error for stale allowlist entry", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
},
|
|
},
|
|
["lodash", "removed-dep"]
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('Package "test-package"');
|
|
expect(errors[0]).toContain('"removed-dep"');
|
|
expect(errors[0]).toContain("not in dependencies or peerDependencies");
|
|
});
|
|
|
|
it("should allow workspace deps in EXTERNAL_DEPENDENCIES without error", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
miniflare: "workspace:*",
|
|
},
|
|
},
|
|
["lodash", "miniflare"]
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should check peerDependencies for stale allowlist entries", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
},
|
|
peerDependencies: {
|
|
vite: "^5.0.0",
|
|
},
|
|
},
|
|
["lodash", "vite"]
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should return multiple errors for multiple issues", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
"undeclared-dep": "^1.0.0",
|
|
},
|
|
},
|
|
["lodash", "stale-dep"]
|
|
);
|
|
expect(errors).toHaveLength(2);
|
|
expect(errors[0]).toContain('"undeclared-dep"');
|
|
expect(errors[1]).toContain('"stale-dep"');
|
|
});
|
|
|
|
it("should ignore devDependencies completely", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
devDependencies: {
|
|
vitest: "^1.0.0",
|
|
typescript: "^5.0.0",
|
|
esbuild: "^0.20.0",
|
|
},
|
|
},
|
|
null // No allowlist needed since devDependencies are ignored
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should ignore devDependencies when validating against allowlist", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
},
|
|
devDependencies: {
|
|
// These should NOT trigger "not in allowlist" errors
|
|
vitest: "^1.0.0",
|
|
typescript: "^5.0.0",
|
|
"some-dev-tool": "^1.0.0",
|
|
},
|
|
},
|
|
["lodash"] // Only lodash in allowlist, devDependencies should be ignored
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should not require devDependencies to be in allowlist", ({ expect }) => {
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
zod: "^3.0.0",
|
|
},
|
|
devDependencies: {
|
|
// Many devDependencies that are NOT in the allowlist
|
|
vitest: "^1.0.0",
|
|
typescript: "^5.0.0",
|
|
esbuild: "^0.20.0",
|
|
prettier: "^3.0.0",
|
|
eslint: "^8.0.0",
|
|
},
|
|
},
|
|
["lodash", "zod"] // Only runtime deps in allowlist
|
|
);
|
|
// Should pass - devDependencies don't need to be in allowlist
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should not count devDependencies as stale allowlist entries", ({
|
|
expect,
|
|
}) => {
|
|
// If a package has something in devDependencies AND in the allowlist,
|
|
// it should be flagged as stale (since devDeps are bundled, not external)
|
|
const errors = validatePackageDependencies(
|
|
"test-package",
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: {
|
|
lodash: "^4.0.0",
|
|
},
|
|
devDependencies: {
|
|
// esbuild is in devDependencies (will be bundled)
|
|
esbuild: "^0.20.0",
|
|
},
|
|
},
|
|
["lodash", "esbuild"] // esbuild in allowlist but only in devDeps = stale
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('"esbuild"');
|
|
expect(errors[0]).toContain("not in dependencies or peerDependencies");
|
|
});
|
|
});
|
|
|
|
describe("getPackageNameFromSpecifier()", () => {
|
|
it("should return the package name from a bare specifier", ({ expect }) => {
|
|
expect(getPackageNameFromSpecifier("lodash")).toBe("lodash");
|
|
});
|
|
|
|
it("should strip subpath imports", ({ expect }) => {
|
|
expect(getPackageNameFromSpecifier("lodash/fp")).toBe("lodash");
|
|
expect(getPackageNameFromSpecifier("semver/functions/satisfies.js")).toBe(
|
|
"semver"
|
|
);
|
|
});
|
|
|
|
it("should preserve scoped package names", ({ expect }) => {
|
|
expect(getPackageNameFromSpecifier("@cloudflare/workers-utils")).toBe(
|
|
"@cloudflare/workers-utils"
|
|
);
|
|
expect(
|
|
getPackageNameFromSpecifier("@cloudflare/workers-utils/test-helpers")
|
|
).toBe("@cloudflare/workers-utils");
|
|
});
|
|
});
|
|
|
|
describe("isBareSpecifier()", () => {
|
|
it("should accept bare package names", ({ expect }) => {
|
|
expect(isBareSpecifier("lodash")).toBe(true);
|
|
expect(isBareSpecifier("@cloudflare/workers-utils")).toBe(true);
|
|
expect(isBareSpecifier("vitest/runtime")).toBe(true);
|
|
});
|
|
|
|
it("should reject relative paths", ({ expect }) => {
|
|
expect(isBareSpecifier("./foo")).toBe(false);
|
|
expect(isBareSpecifier("../bar")).toBe(false);
|
|
expect(isBareSpecifier("/abs/path")).toBe(false);
|
|
});
|
|
|
|
it("should reject empty specifiers", ({ expect }) => {
|
|
expect(isBareSpecifier("")).toBe(false);
|
|
});
|
|
|
|
it("should reject Node.js built-ins (with and without prefix)", ({
|
|
expect,
|
|
}) => {
|
|
expect(isBareSpecifier("node:fs")).toBe(false);
|
|
expect(isBareSpecifier("fs")).toBe(false);
|
|
expect(isBareSpecifier("node:child_process")).toBe(false);
|
|
expect(isBareSpecifier("child_process")).toBe(false);
|
|
expect(isBareSpecifier("assert")).toBe(false);
|
|
});
|
|
|
|
it("should reject Cloudflare/workerd built-ins", ({ expect }) => {
|
|
expect(isBareSpecifier("cloudflare:workers")).toBe(false);
|
|
expect(isBareSpecifier("workerd:unsafe")).toBe(false);
|
|
});
|
|
|
|
it("should reject bundler virtual modules", ({ expect }) => {
|
|
expect(isBareSpecifier("virtual:react-router")).toBe(false);
|
|
expect(isBareSpecifier("wrangler:modules-watch")).toBe(false);
|
|
});
|
|
|
|
it("should reject ALL_CAPS virtual modules", ({ expect }) => {
|
|
expect(isBareSpecifier("__VITEST_POOL_WORKERS_DEFINES")).toBe(false);
|
|
expect(isBareSpecifier("__BUILD_CONFIG")).toBe(false);
|
|
});
|
|
|
|
it("should reject specifiers that are not package-name shaped", ({
|
|
expect,
|
|
}) => {
|
|
expect(isBareSpecifier(",")).toBe(false);
|
|
expect(isBareSpecifier("some random text")).toBe(false);
|
|
expect(isBareSpecifier("ASSERT.IN.MIXED-CASE")).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("extractBareImports()", () => {
|
|
it("should extract named imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(`import { x } from "lodash";`);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should extract default imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(`import x from "lodash";`);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should extract namespace imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(`import * as x from "lodash";`);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should extract side-effect imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(`import "lodash";`);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should extract re-exports", async ({ expect }) => {
|
|
const imports = await extractBareImports(`export { x } from "lodash";`);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should extract require() calls", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`const x = require("lodash"); require("foo");`
|
|
);
|
|
expect([...imports].sort()).toEqual(["foo", "lodash"]);
|
|
});
|
|
|
|
it("should extract dynamic import() calls with string literals", async ({
|
|
expect,
|
|
}) => {
|
|
const imports = await extractBareImports(
|
|
`const x = await import("lodash");`
|
|
);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should strip subpath imports down to package name", async ({
|
|
expect,
|
|
}) => {
|
|
const imports = await extractBareImports(
|
|
`import x from "semver/functions/satisfies.js";`
|
|
);
|
|
expect([...imports]).toEqual(["semver"]);
|
|
});
|
|
|
|
it("should skip relative imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`import x from "./foo"; import y from "../bar";`
|
|
);
|
|
expect([...imports]).toEqual([]);
|
|
});
|
|
|
|
it("should skip Node built-in imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`import fs from "node:fs"; const path = require("node:path");`
|
|
);
|
|
expect([...imports]).toEqual([]);
|
|
});
|
|
|
|
it("should skip Cloudflare/workerd built-in imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`import { env } from "cloudflare:workers"; import x from "workerd:unsafe";`
|
|
);
|
|
expect([...imports]).toEqual([]);
|
|
});
|
|
|
|
it("should skip imports inside line comments", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`// import x from "lodash";\nimport y from "react";`
|
|
);
|
|
expect([...imports]).toEqual(["react"]);
|
|
});
|
|
|
|
it("should skip imports inside block comments", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`/* import x from "lodash"; */\nimport y from "react";`
|
|
);
|
|
expect([...imports]).toEqual(["react"]);
|
|
});
|
|
|
|
it("should skip imports inside template literals (regression: createViteConfig)", async ({
|
|
expect,
|
|
}) => {
|
|
// Regression test: wrangler's createViteConfig bundles the literal text
|
|
// of a vite.config.ts into a template literal. The regex-based scanner
|
|
// used to match `import { defineConfig } from "vite"` as a real import.
|
|
const imports = await extractBareImports(
|
|
[
|
|
"function createViteConfig() {",
|
|
' const content = `import { cloudflare } from "@cloudflare/vite-plugin";',
|
|
'import { defineConfig } from "vite";',
|
|
"",
|
|
"export default defineConfig({",
|
|
"\tplugins: [cloudflare()],",
|
|
"});",
|
|
"`;",
|
|
" return content;",
|
|
"}",
|
|
'import real from "react";',
|
|
].join("\n")
|
|
);
|
|
expect([...imports]).toEqual(["react"]);
|
|
});
|
|
|
|
it("should skip imports inside single- and double-quoted strings", async ({
|
|
expect,
|
|
}) => {
|
|
const imports = await extractBareImports(
|
|
[
|
|
'const a = "import { x } from \\"lodash\\";";',
|
|
"const b = 'import { y } from \"react\";';",
|
|
'import real from "commander";',
|
|
].join("\n")
|
|
);
|
|
expect([...imports]).toEqual(["commander"]);
|
|
});
|
|
|
|
it("should not match `from` keywords that aren't part of import/export", async ({
|
|
expect,
|
|
}) => {
|
|
const imports = await extractBareImports(
|
|
`function foo() { return "hello"; } const z = "from";`
|
|
);
|
|
expect([...imports]).toEqual([]);
|
|
});
|
|
|
|
it("should deduplicate imports", async ({ expect }) => {
|
|
const imports = await extractBareImports(
|
|
`import { x } from "lodash";\nimport { y } from "lodash";`
|
|
);
|
|
expect([...imports]).toEqual(["lodash"]);
|
|
});
|
|
|
|
it("should handle multiple imports in one file", async ({ expect }) => {
|
|
const imports = await extractBareImports(`
|
|
import { x } from "lodash";
|
|
import y from "react";
|
|
import "polyfill";
|
|
const z = require("commander");
|
|
`);
|
|
expect([...imports].sort()).toEqual([
|
|
"commander",
|
|
"lodash",
|
|
"polyfill",
|
|
"react",
|
|
]);
|
|
});
|
|
});
|
|
|
|
describe("validateDistImports()", () => {
|
|
it("should pass when all imports are declared dependencies", ({ expect }) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
dependencies: { lodash: "^4.0.0", react: "^18.0.0" },
|
|
},
|
|
new Set(["lodash", "react"])
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should pass when imports are peerDependencies", ({ expect }) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
peerDependencies: { vitest: "^4.0.0" },
|
|
},
|
|
new Set(["vitest"])
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should allow self-imports without error", ({ expect }) => {
|
|
const errors = validateDistImports(
|
|
"my-package",
|
|
{ name: "my-package" },
|
|
new Set(["my-package"])
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should flag devDependency-only imports with a tailored message", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
devDependencies: { undici: "^7.0.0" },
|
|
},
|
|
new Set(["undici"])
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('"undici"');
|
|
expect(errors[0]).toContain("only a devDependency");
|
|
expect(errors[0]).toContain("IGNORED_DIST_IMPORTS");
|
|
});
|
|
|
|
it("should flag undeclared imports", ({ expect }) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{ name: "test-package" },
|
|
new Set(["mystery-package"])
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('"mystery-package"');
|
|
expect(errors[0]).toContain(
|
|
"not declared in dependencies or peerDependencies"
|
|
);
|
|
});
|
|
|
|
it("should skip imports in the ignored list", ({ expect }) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
devDependencies: { "@netlify/build-info": "^1.0.0" },
|
|
},
|
|
new Set(["react-router", "@angular/ssr"]),
|
|
["react-router", "@angular/ssr"]
|
|
);
|
|
expect(errors).toEqual([]);
|
|
});
|
|
|
|
it("should still flag non-ignored imports when ignored list is non-empty", ({
|
|
expect,
|
|
}) => {
|
|
const errors = validateDistImports(
|
|
"test-package",
|
|
{
|
|
name: "test-package",
|
|
devDependencies: { undici: "^7.0.0" },
|
|
},
|
|
new Set(["undici", "react-router"]),
|
|
["react-router"]
|
|
);
|
|
expect(errors).toHaveLength(1);
|
|
expect(errors[0]).toContain('"undici"');
|
|
});
|
|
});
|
|
|
|
describe("getEntryPointPaths()", () => {
|
|
it("should collect main field", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
main: "dist/index.js",
|
|
});
|
|
expect(paths).toEqual(["dist/index.js"]);
|
|
});
|
|
|
|
it("should collect module field", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
module: "dist/index.mjs",
|
|
});
|
|
expect(paths).toEqual(["dist/index.mjs"]);
|
|
});
|
|
|
|
it("should walk nested exports object", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
exports: {
|
|
".": {
|
|
import: "./dist/index.mjs",
|
|
require: "./dist/index.cjs",
|
|
types: "./dist/index.d.ts",
|
|
},
|
|
"./test-helpers": {
|
|
import: "./dist/test-helpers/index.mjs",
|
|
},
|
|
},
|
|
});
|
|
expect(paths.sort()).toEqual([
|
|
"./dist/index.cjs",
|
|
"./dist/index.d.ts",
|
|
"./dist/index.mjs",
|
|
"./dist/test-helpers/index.mjs",
|
|
]);
|
|
});
|
|
|
|
it("should collect string bin entries", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
bin: "./bin/cli.js",
|
|
});
|
|
expect(paths).toEqual(["./bin/cli.js"]);
|
|
});
|
|
|
|
it("should collect object bin entries", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
bin: { foo: "./bin/foo.js", bar: "./bin/bar.js" },
|
|
});
|
|
expect(paths.sort()).toEqual(["./bin/bar.js", "./bin/foo.js"]);
|
|
});
|
|
|
|
it("should deduplicate paths across fields", ({ expect }) => {
|
|
const paths = getEntryPointPaths({
|
|
name: "p",
|
|
main: "./dist/index.js",
|
|
module: "./dist/index.js",
|
|
exports: { ".": "./dist/index.js" },
|
|
});
|
|
expect(paths).toEqual(["./dist/index.js"]);
|
|
});
|
|
|
|
it("should return empty array when no entry points are declared", ({
|
|
expect,
|
|
}) => {
|
|
const paths = getEntryPointPaths({ name: "p" });
|
|
expect(paths).toEqual([]);
|
|
});
|
|
});
|
|
|
|
describe("getPublicPackages()", () => {
|
|
it("should return only non-private packages", async ({ expect }) => {
|
|
const packages = await getPublicPackages();
|
|
|
|
// All returned packages should be non-private
|
|
for (const pkg of packages) {
|
|
expect(pkg.packageJson.private).not.toBe(true);
|
|
}
|
|
|
|
// Should include known public packages
|
|
const packageNames = packages.map((p) => p.packageJson.name);
|
|
expect(packageNames).toContain("wrangler");
|
|
expect(packageNames).toContain("miniflare");
|
|
expect(packageNames).toContain("create-cloudflare");
|
|
expect(packageNames).toContain("@cloudflare/autoconfig");
|
|
});
|
|
|
|
it("should not include private packages", async ({ expect }) => {
|
|
const packages = await getPublicPackages();
|
|
const packageNames = packages.map((p) => p.packageJson.name);
|
|
|
|
// These are known private packages
|
|
expect(packageNames).not.toContain("@cloudflare/workers-shared");
|
|
});
|
|
});
|