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
7 changes: 3 additions & 4 deletions e2e/cli/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,10 @@ describe("dot deploy — preflight and validation", () => {
result.exitCode,
`expected non-zero exit for --env mainnet, got 0\n${output}`,
).not.toBe(0);
// Exact wording from src/commands/deploy/index.ts: "`--env mainnet` is
// not yet supported. Use `--env testnet` (default) while mainnet launch
// is pending."
// Exact wording from src/config.ts::getChainConfig():
// "--env polkadot is not yet supported. Use --env paseo-next-v2 (default)."
expect(output).toContain("not yet supported");
expect(output).toContain("--env testnet");
expect(output).toContain("--env paseo-next-v2");
});

test("detects foundry contracts type in project", async () => {
Expand Down
26 changes: 14 additions & 12 deletions e2e/cli/fixtures/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ export const BOB: TestAccount = devAccount("Bob");
* publish path (storage / re-deploy / cross-owner collision); reuse a single
* domain for the preflight / validation tests.
*
* DotNS classifies names with a 6-8 character base plus exactly two trailing
* digits as PopLite. Keep these labels in that shape so E2E tests do not
* accidentally require Full personhood on testnet.
* DotNS classifies names with a base of ≥ 9 chars plus exactly two trailing
* digits as NoStatus (no PoP required). Keep these labels in that shape so
* the E2E deployer (NoStatus signer) can register them on any environment,
* including paseo-next-v2 where setUserPopStatus is owner-gated and
* self-attestation is not available.
*
* NOTE: do not assert on the registry state of `preflight` — it's shared by
* six tests in the same file and the metadata at any moment reflects whichever
Expand All @@ -105,28 +107,28 @@ export const E2E_DOMAINS = {
* tests do reach `registry.publish`. SIGNER ends up owning this domain
* regardless; subsequent runs are same-owner re-publishes.
*/
preflight: "e2epre00",
preflight: "e2eprefly00",
/** Used by the storage-phase happy path. */
storage: "e2estr00",
storage: "e2estorag00",
/** Used by the same-owner re-deploy test. */
redeploy: "e2ered00",
redeploy: "e2eredepl00",
/** Used by the cross-owner collision test (BOB tries to take SIGNER's). */
collision: "e2ecol00",
collision: "e2ecollis00",
/**
* Phase 3 cell domains — registered by `tools/register-e2e-fixtures.ts`.
* Owned by SIGNER; subsequent runs are same-owner re-publishes.
* Not yet wired to any test — see Phase 4 of docs-internal/2026-05-02-e2e-test-suite-design.md.
*/
foundry: "e2efnd00",
cdm: "e2ecdm00",
hardhat: "e2ehat00",
multi: "e2emul00",
foundry: "e2efoundry00",
cdm: "e2ecdmapp00",
hardhat: "e2ehardhat00",
multi: "e2emultip00",
/**
* Used by the nightly-chaos-sigint cell only. The deploy is interrupted by
* SIGINT before it completes, so this domain is never actually registered.
* It is kept separate from `storage` to avoid any race with the happy-path
* storage test in test-publish when both run in a nightly that triggers all
* matrices.
*/
chaos: "e2echs00",
chaos: "e2echaosp00",
} as const;
28 changes: 14 additions & 14 deletions e2e/cli/mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,20 @@ describe("dot mod — clone", () => {
},
);

test("exits non-zero with signer suggestion when no signer available", async () => {
const tempHome = makeTempDir("dot-e2e-mod-home-");
const cwd = makeTempDir("dot-e2e-mod-cwd-");
const result = await dot(["mod", "some-app.dot"], { home: tempHome, cwd });
expect(result.exitCode).not.toBe(0);
const output = result.stdout + result.stderr;
// Exact wording from src/utils/signer.ts SignerNotAvailableError:
// `No signer available. Run "dot init" to log in, or pass --suri //Alice for dev.`
// The previous regex /signer|init|log.?in/i matched any of those words
// anywhere — including help text — so it passed even on early crashes
// that never reached the signer-resolution path.
expect(output).toContain("No signer available");
expect(output).toContain("dot init");
});
test(
"exits non-zero for unknown domain with no prior session (mod is signer-less)",
{ timeout: 60_000 },
async () => {
const tempHome = makeTempDir("dot-e2e-mod-home-");
const cwd = makeTempDir("dot-e2e-mod-cwd-");
const result = await dot(["mod", "some-app.dot"], { home: tempHome, cwd, timeout: 60_000 });
expect(result.exitCode).not.toBe(0);
const output = result.stdout + result.stderr;
// dot mod is signer-less — it proceeds directly to the registry lookup.
// An unknown domain produces: App "some-app.dot" not found in registry
expect(output).toContain("not found in registry");
},
);
});

describe("dot mod — registry miss", () => {
Expand Down
9 changes: 6 additions & 3 deletions src/utils/deploy/availability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,12 @@ export async function checkDomainAvailability(

const plan: DeployPlan = { action: "register", needsPopUpgrade };

// Names that require Proof-of-Personhood are still registrable on
// testnet — bulletin-deploy self-attests during `register()` via
// `setUserPopStatus`. Surface it as an advisory note, not a blocker.
// Names that require Proof-of-Personhood are registrable on testnet
// environments where self-attestation is allowed (bulletin-deploy calls
// `setUserPopStatus` during `register()`). On paseo-next-v2 that call
// is owner-gated, so a NoStatus signer cannot self-attest and the
// deploy will fail at the network phase. We surface this as an advisory
// note rather than a hard block because the rule varies per environment.
if (
classification.status === POP_STATUS_LITE ||
classification.status === POP_STATUS_FULL
Expand Down
Loading