Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE_WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ gh pr merge PR_NUMBER --merge --admin --delete-branch
<summary>Choosing the relevant check</summary>

- For broad product, Worker, policy, or generated-output changes: `npm run check`.
- For maintenance script changes, such as `scripts/doctor.mjs`, `scripts/install.mjs`, `scripts/upgrade.mjs`, or shared
- For maintenance script changes, such as `scripts/doctor.mjs`, `scripts/setup.mjs`, `scripts/upgrade.mjs`, or shared
script libraries: run the focused test that covers the changed path, then `npm run check` before merge.
- For doctor output changes: `npm run doctor -- --json`.
- For opt-in upstream nudge changes: `npm run doctor -- --json --check-upstream`.
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
"local-install": "node scripts/local-install.mjs",
"local-publish": "node scripts/local-publish.mjs",
"optimize:badges": "find defaults/public -name 'v8s-redirected*.svg' -print0 | xargs -0 svgo --config scripts/svgo.config.mjs",
"setup": "node scripts/install.mjs",
"setup": "node scripts/setup.mjs",
"smoke": "npm run smoke:analytics",
"smoke:analytics": "npm run build && node scripts/smoke-analytics.mjs",
"test": "npm run test:all",
"test:all": "npm run test:worker && npm run test:registry && npm run test:install && npm run test:maintenance && npm run test:upstream-release && npm run test:build-core && npm run test:build-html-core",
"test:all": "npm run test:worker && npm run test:registry && npm run test:install && npm run test:install-core && npm run test:maintenance && npm run test:upstream-release && npm run test:build-core && npm run test:build-html-core",
"test:build-core": "node scripts/build-site-core.test.mjs",
"test:build-html-core": "node scripts/build-html-core.test.mjs",
"test:install": "node scripts/install.test.mjs",
"test:install-core": "node scripts/install-core.test.mjs",
"test:maintenance": "node scripts/maintenance.test.mjs",
"test:registry": "node scripts/registry.test.mjs",
"test:upstream-release": "node scripts/upstream-release.test.mjs",
Expand Down
112 changes: 112 additions & 0 deletions scripts/install-core.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env node

import assert from "node:assert/strict";
import {
analyticsDisclosureDefault,
defaultBrandingSlogan,
defaultContactEmail,
normalizeAccessTeamDomain,
normalizeArgs,
normalizeAnalyticsProviders,
normalizeDomain,
normalizeLanguages,
normalizeRandomSlugLength,
normalizeSloganMap,
parseArgs,
slugifyOwner,
slugifyWorker,
suggestWordmarkSplit
} from "./lib/install/core.mjs";

{
assert.deepEqual(parseArgs(["--domain", "https://Go.Example/path", "--no-check", "--customize-public"]), {
analytics: "disabled",
check: false,
customizePublic: true,
dryRun: false,
domain: "https://Go.Example/path",
force: false,
owner: "owner"
});
assert.throws(() => parseArgs(["--domain"]), /Missing value/);
assert.throws(() => parseArgs(["unexpected"]), /Unknown argument/);
}

{
assert.equal(normalizeDomain("https://Go.Example/path"), "go.example");
assert.equal(slugifyWorker("Go Example!!!"), "go-example");
assert.equal(slugifyOwner("Team Name!"), "team-name");
assert.deepEqual(normalizeLanguages("fr-CA,en,fr,de"), ["en", "fr", "de"]);
assert.equal(normalizeAnalyticsProviders("Umami, FATHOM"), "umami,fathom");
assert.throws(() => normalizeAnalyticsProviders("plausible"), /Unsupported analytics provider/);
assert.equal(normalizeRandomSlugLength("12"), 12);
assert.throws(() => normalizeRandomSlugLength("0"), /Random slug length/);
}

{
assert.equal(defaultContactEmail("security", "https://Example.com/path"), "security@example.com");
assert.equal(normalizeAccessTeamDomain("https://team.cloudflareaccess.com/"), "team.cloudflareaccess.com");
assert.deepEqual(suggestWordmarkSplit("go.example"), { black: "go.", green: "example" });
}

{
assert.equal(analyticsDisclosureDefault("disabled"), "No analytics enabled.");
assert.equal(
analyticsDisclosureDefault("umami"),
"Privacy-respecting analytics are configured for operations, security, and reliability."
);
assert.equal(
defaultBrandingSlogan({ operatorLegalName: "Example Inc." }, "en"),
"A short-link service for Example Inc.'s projects"
);
assert.deepEqual(normalizeSloganMap("Hello", ["en", "fr"], { operatorLegalName: "Example Inc." }), {
en: "Hello",
fr: "Un service de liens courts pour les projets de Example Inc."
});
}

{
const normalized = normalizeArgs(
{
analytics: "umami",
domain: "https://Go.Example/path",
owner: "Team Name",
operatorAbuseContact: "abuse@example.com",
operatorSecurityContact: "security@example.com",
operatorTimezone: "America/Toronto",
wordmarkBlack: "Go.",
wordmarkGreen: "Example"
},
{
defaultRandomSlugLength: 5,
fallbackLastUpdated: "2026-06-05"
}
);

assert.equal(normalized.domain, "go.example");
assert.equal(normalized.workerName, "go-example");
assert.equal(normalized.owner, "team-name");
assert.equal(normalized.randomSlugLength, 5);
assert.equal(normalized.operator.short_domain, "go.example");
assert.equal(normalized.operator.last_updated, "2026-06-05");
assert.equal(normalized.operator.analytics_retention, "180 days");
assert.equal(normalized.configureBranding, true);
}

{
assert.throws(
() =>
normalizeArgs(
{
domain: "go.example",
operatorAbuseContact: "abuse@example.com",
operatorSecurityContact: "security@example.com",
operatorTimezone: "-4"
},
{ fallbackLastUpdated: "2026-06-05" }
),
/Operator timezone must be an IANA timezone name/
);
}

console.log("install core tests ok");
2 changes: 1 addition & 1 deletion scripts/install.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function makeFixture() {
}

function runSetup(cwd, extraArgs) {
return execFileSync(process.execPath, ["scripts/install.mjs", "--no-check", ...extraArgs], {
return execFileSync(process.execPath, ["scripts/setup.mjs", "--no-check", ...extraArgs], {
cwd,
encoding: "utf8",
env: { ...process.env, V8S_INTERNAL_SETUP: "1" },
Expand Down
Loading