mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 09:39:25 +00:00
* test(codex): deslop s003 tests * test(gateway): deslop s010 tests * test(agents): deslop s013 tests * test(commands): deslop s011 tests * test(gateway): deslop s014 tests * test(gateway): deslop s019 tests * test(infra): deslop s016 tests * test(agents): deslop s020 tests * test(scripts): deslop s017 tests * test(auto-reply): deslop s021 tests * test: align d009 replay with current fixture contracts * test(agents): remove orphaned BTW fixture export * test: preserve independent regression coverage in d009 Restore eight independent authentication, retry, transcript, goal, reply ownership, and Xcode coverage contracts identified during review. Final correction review passed; final Testbox validation remains pending after lease and transport failures.
384 lines
22 KiB
TypeScript
384 lines
22 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { describe, expect, it } from "vitest";
|
|
import { extractFunctionBody } from "./install-ps1.test-support.js";
|
|
|
|
const SCRIPT_PATH = "scripts/install.ps1";
|
|
|
|
describe("install.ps1 source contracts", () => {
|
|
const source = readFileSync(SCRIPT_PATH, "utf8");
|
|
|
|
it("pipes the SQLite probe to an application Node executable", () => {
|
|
const checkNodeBody = extractFunctionBody(source, "Check-Node");
|
|
expect(checkNodeBody).toContain("Get-Command node -CommandType Application");
|
|
expect(checkNodeBody).toContain("SELECT sqlite_version() AS version");
|
|
expect(checkNodeBody).toContain("$sqliteProbe | & $nodePath -");
|
|
expect(checkNodeBody).not.toContain("& $nodePath -e");
|
|
});
|
|
|
|
it("discovers a winget Node install before the machine PATH refreshes", () => {
|
|
const installNodeBody = extractFunctionBody(source, "Install-Node");
|
|
const packageManagerBody = extractFunctionBody(source, "Invoke-NodePackageManagerInstall");
|
|
const addInstalledNodeBody = extractFunctionBody(source, "Add-InstalledNodeToProcessPath");
|
|
expect(installNodeBody).toContain("-DiscoverProgramFilesNode");
|
|
expect(packageManagerBody).toContain("Add-InstalledNodeToProcessPath | Out-Null");
|
|
expect(addInstalledNodeBody).toContain("$env:ProgramW6432");
|
|
expect(addInstalledNodeBody).toContain("$env:ProgramFiles");
|
|
expect(addInstalledNodeBody).toContain('Join-Path $nodeDir "node.exe"');
|
|
expect(addInstalledNodeBody).toContain("Add-ToProcessPath $nodeDir");
|
|
});
|
|
|
|
it("runs npm install through the resolved command with quiet CI defaults", () => {
|
|
const npmInstallBody = extractFunctionBody(source, "Install-OpenClaw");
|
|
expect(npmInstallBody).toContain(
|
|
"$npmOutput = Invoke-NpmCommand -CommandPath $npmCommand -WorkingDirectory $npmCwd -Arguments",
|
|
);
|
|
expect(npmInstallBody).toContain("$npmDebugLogRoots = @(Get-NpmDebugLogRootCandidates)");
|
|
expect(npmInstallBody).toContain('$npmInstallArguments = @("install", "-g")');
|
|
expect(npmInstallBody).toContain('Write-Host "[!] npm install failed; retrying once"');
|
|
expect(
|
|
npmInstallBody.match(
|
|
/Invoke-NpmCommand -CommandPath \$npmCommand -WorkingDirectory \$npmCwd -Arguments \$npmInstallArguments/g,
|
|
),
|
|
).toHaveLength(2);
|
|
expect(npmInstallBody).toContain('$env:NPM_CONFIG_LOGLEVEL = "error"');
|
|
expect(npmInstallBody).toContain('$env:NPM_CONFIG_UPDATE_NOTIFIER = "false"');
|
|
expect(npmInstallBody).toContain('$env:NPM_CONFIG_FUND = "false"');
|
|
expect(npmInstallBody).toContain('$env:NPM_CONFIG_AUDIT = "false"');
|
|
expect(npmInstallBody).not.toContain("NPM_CONFIG_SCRIPT_SHELL");
|
|
expect(npmInstallBody).toContain('$freshnessArgs = @("--min-release-age=0")');
|
|
expect(npmInstallBody).toContain("Remove-Item Env:NPM_CONFIG_BEFORE");
|
|
expect(npmInstallBody).toContain("Remove-Item Env:NPM_CONFIG_MIN_RELEASE_AGE");
|
|
expect(npmInstallBody).toContain("$env:NPM_CONFIG_LOGLEVEL = $prevLogLevel");
|
|
expect(npmInstallBody).toContain("$env:NPM_CONFIG_BEFORE = $prevBefore");
|
|
expect(npmInstallBody).toContain(
|
|
"Write-NpmInstallFailureDetails -Output $npmOutput -CacheRoots $npmDebugLogRoots",
|
|
);
|
|
expect(source).toContain("function Get-LatestNpmDebugLogPath {");
|
|
expect(source).toContain("Get-Content -LiteralPath $latestLog -Tail 120");
|
|
});
|
|
|
|
it("does not force npm or pnpm lifecycle scripts through cmd.exe", () => {
|
|
const ensurePnpmBody = extractFunctionBody(source, "Ensure-Pnpm");
|
|
const npmInstallBody = extractFunctionBody(source, "Install-OpenClaw");
|
|
const gitInstallBody = extractFunctionBody(source, "Install-OpenClawFromGit");
|
|
|
|
expect(ensurePnpmBody).not.toContain("NPM_CONFIG_SCRIPT_SHELL");
|
|
expect(npmInstallBody).not.toContain("NPM_CONFIG_SCRIPT_SHELL");
|
|
expect(gitInstallBody).not.toContain("NPM_CONFIG_SCRIPT_SHELL");
|
|
});
|
|
|
|
it("rejects a git checkout without a commit before updating it", () => {
|
|
const guardBody = extractFunctionBody(source, "Assert-GitCheckoutHasCommit");
|
|
const gitInstallBody = extractFunctionBody(source, "Install-OpenClawFromGit");
|
|
|
|
expect(guardBody).toContain('"--git-dir=$gitDir"');
|
|
expect(guardBody).toContain('"--work-tree=$RepoDir"');
|
|
expect(guardBody).toContain('rev-parse --verify --quiet "HEAD^{commit}"');
|
|
expect(guardBody).toContain("Git checkout has no commit");
|
|
expect(guardBody).not.toContain("Remove-Item");
|
|
expect(guardBody).not.toContain("Move-Item");
|
|
expect(gitInstallBody).toContain("Assert-GitCheckoutHasCommit -RepoDir $RepoDir");
|
|
});
|
|
|
|
it("runs Windows command shims from a Windows-local cwd", () => {
|
|
const commandSafeBody = extractFunctionBody(source, "Invoke-CommandFromWindowsSafeDirectory");
|
|
const npmCommandBody = extractFunctionBody(source, "Invoke-NpmCommand");
|
|
const openClawPathBody = extractFunctionBody(source, "Ensure-OpenClawOnPath");
|
|
const ensurePnpmBody = extractFunctionBody(source, "Ensure-Pnpm");
|
|
const mainBody = extractFunctionBody(source, "Main");
|
|
|
|
expect(commandSafeBody).toContain("Get-WindowsCommandSafeDirectory");
|
|
expect(commandSafeBody).toContain("$WorkingDirectory");
|
|
expect(commandSafeBody).toContain("Push-Location -LiteralPath $safeDir");
|
|
expect(commandSafeBody).toContain("& $CommandPath @Arguments");
|
|
expect(commandSafeBody).toContain("Pop-Location");
|
|
expect(npmCommandBody).toContain("Invoke-CommandFromWindowsSafeDirectory");
|
|
expect(openClawPathBody).toContain('Invoke-NpmCommand -Arguments @("config", "get", "prefix")');
|
|
expect(ensurePnpmBody).toContain(
|
|
'@("enable", "--install-directory", $InstallDirectory, "pnpm")',
|
|
);
|
|
expect(ensurePnpmBody).toContain(
|
|
"Invoke-NpmCommand -CommandPath $npmCommand -Arguments $installArgs",
|
|
);
|
|
expect(mainBody).toContain("Remove-PreviousNpmOwner");
|
|
expect(mainBody).toContain("Remove-PreviousGitWrapper");
|
|
expect(mainBody).toContain("Start-NpmShimBackup");
|
|
expect(mainBody).toContain("Restore-NpmShimBackup");
|
|
expect(mainBody).toContain("Complete-NpmShimBackup");
|
|
expect(mainBody).toContain(
|
|
'Invoke-NpmCommand -Arguments @("list", "-g", "--depth", "0", "--json")',
|
|
);
|
|
});
|
|
|
|
it("shares the canonical temp root with downloads and Windows command shims", () => {
|
|
for (const name of ["Install-PortableNode", "Install-PortableGit"]) {
|
|
expect(extractFunctionBody(source, name)).toContain(
|
|
"Join-Path $script:InstallerTempDirectory",
|
|
);
|
|
}
|
|
expect(extractFunctionBody(source, "Get-WindowsCommandSafeDirectory")).toContain(
|
|
"return $script:InstallerTempDirectory",
|
|
);
|
|
expect(source.match(/^Initialize-InstallerTempDirectory$/gm)).toHaveLength(1);
|
|
});
|
|
|
|
it("rejects OpenClaw GitHub source targets for npm installs", () => {
|
|
const npmInstallBody = extractFunctionBody(source, "Install-OpenClaw");
|
|
const sourceTargetBody = extractFunctionBody(source, "Test-OpenClawSourcePackageInstallSpec");
|
|
expect(sourceTargetBody).toContain('$normalizedTag -eq "main"');
|
|
expect(sourceTargetBody).toContain("^github:openclaw/openclaw");
|
|
expect(npmInstallBody).toContain("Test-OpenClawSourcePackageInstallSpec -RequestedTag $Tag");
|
|
expect(npmInstallBody).toContain("npm installs do not support OpenClaw GitHub source targets");
|
|
expect(npmInstallBody).toContain("-InstallMethod git -Tag main");
|
|
});
|
|
|
|
it("does not read project npmrc when choosing global install freshness args", () => {
|
|
const rawKeyBody = extractFunctionBody(source, "Test-NpmConfigRawKey");
|
|
expect(rawKeyBody).not.toContain("Get-Location");
|
|
expect(rawKeyBody).not.toContain('Join-Path (Get-Location) ".npmrc"');
|
|
});
|
|
|
|
it("preserves the min-release-age probe status before raw npmrc detection", () => {
|
|
const npmInstallBody = extractFunctionBody(source, "Install-OpenClaw");
|
|
const probeStatusCapture = npmInstallBody.indexOf("$minReleaseAgeStatus = $LASTEXITCODE");
|
|
const rawKeyProbe = npmInstallBody.indexOf("Test-NpmConfigRawKey -Key");
|
|
expect(probeStatusCapture).toBeGreaterThan(-1);
|
|
expect(rawKeyProbe).toBeGreaterThan(-1);
|
|
expect(probeStatusCapture).toBeLessThan(rawKeyProbe);
|
|
expect(npmInstallBody).toContain(
|
|
"} elseif ($minReleaseAgeStatus -ne 0 -or -not $minReleaseAge",
|
|
);
|
|
expect(npmInstallBody).toContain(
|
|
'Invoke-NpmCommand -CommandPath $npmCommand -WorkingDirectory $npmCwd -Arguments @("config", "get", "min-release-age", "--global")',
|
|
);
|
|
expect(npmInstallBody).toContain(
|
|
'Invoke-NpmCommand -CommandPath $npmCommand -WorkingDirectory $npmCwd -Arguments @("config", "get", "before", "--global")',
|
|
);
|
|
});
|
|
|
|
it("preserves caller-relative local tarball install specs before safe-cwd npm calls", () => {
|
|
const resolveSpecBody = extractFunctionBody(source, "Resolve-NpmOpenClawInstallSpec");
|
|
const localSpecBody = extractFunctionBody(source, "Resolve-LocalNpmPackageInstallSpec");
|
|
const localPathBody = extractFunctionBody(source, "Resolve-LocalNpmPackagePath");
|
|
|
|
expect(resolveSpecBody).toContain(
|
|
"Resolve-LocalNpmPackageInstallSpec -InstallSpec $trimmedTag",
|
|
);
|
|
expect(localSpecBody).toContain("$InstallSpec -match '^file:(?<path>.+)$'");
|
|
expect(localSpecBody).toContain("Resolve-LocalNpmPackagePath -PackagePath $filePath");
|
|
expect(localSpecBody).toContain(").AbsoluteUri");
|
|
expect(localSpecBody).toContain("$InstallSpec -notmatch '^\\.\\.?[\\\\/]'");
|
|
expect(localSpecBody).toContain("$InstallSpec -notmatch '\\.tgz$'");
|
|
expect(localPathBody).toContain("Resolve-Path -LiteralPath $PackagePath");
|
|
expect(localPathBody).toContain("[System.IO.Path]::GetFullPath($PackagePath)");
|
|
});
|
|
|
|
it("falls back to a user-local portable Node.js bootstrap when package managers are absent", () => {
|
|
const installNodeBody = extractFunctionBody(source, "Install-Node");
|
|
const portableNodeBody = extractFunctionBody(source, "Install-PortableNode");
|
|
const portableNodeRootBody = extractFunctionBody(source, "Get-PortableNodeRoot");
|
|
const portableNodePathBody = extractFunctionBody(source, "Ensure-PortableNodeOnUserPath");
|
|
const userPathBody = extractFunctionBody(source, "Add-ToUserPath");
|
|
const depsRootBody = extractFunctionBody(source, "Get-OpenClawDepsRoot");
|
|
const resolveNodeBody = extractFunctionBody(source, "Resolve-PortableNodeDownload");
|
|
const expandNodeBody = extractFunctionBody(source, "Expand-PortableNodeArchive");
|
|
|
|
expect(installNodeBody).toContain("Install-PortableNode");
|
|
expect(installNodeBody).toContain("Portable Node.js bootstrap failed");
|
|
expect(installNodeBody).toContain("Error: Could not install Node.js automatically.");
|
|
expect(depsRootBody).toContain("OpenClaw\\deps");
|
|
expect(portableNodeRootBody).toContain("portable-node");
|
|
expect(portableNodeBody).toContain("Ensure-PortableNodeOnUserPath");
|
|
expect(portableNodeBody).toContain("Bootstrapping user-local portable Node.js");
|
|
expect(portableNodeBody).toContain(
|
|
"Expand-PortableNodeArchive -ZipPath $tmpZip -DestinationPath $portableRoot",
|
|
);
|
|
expect(portableNodeBody).not.toContain("Copy-Item");
|
|
expect(portableNodeBody).not.toContain('Join-Path $nodeDir.FullName "*"');
|
|
expect(portableNodePathBody).toContain("Add-ToUserPath $nodeDir");
|
|
expect(userPathBody).toContain(
|
|
'[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")',
|
|
);
|
|
expect(portableNodeBody).toContain(
|
|
"Save-InstallerDownload -Uri $download.Url -OutFile $tmpZip",
|
|
);
|
|
expect(portableNodeBody).toContain("Expand-PortableNodeArchive");
|
|
expect(portableNodeBody).not.toContain("Expand-Archive");
|
|
expect(portableNodeBody).not.toContain("New-Item -ItemType Directory -Force -Path $tmpExtract");
|
|
expect(expandNodeBody).toContain("Get-Command tar");
|
|
expect(expandNodeBody).toContain(
|
|
"Copy-Item -LiteralPath $nodeDir.FullName -Destination $DestinationPath -Recurse -Force",
|
|
);
|
|
expect(expandNodeBody).toContain("System.IO.Compression.ZipFile");
|
|
expect(resolveNodeBody).toContain("https://nodejs.org/dist/index.json");
|
|
expect(resolveNodeBody).toContain(
|
|
'Get-WebRequestTimeoutParameters -CommandName "Invoke-RestMethod"',
|
|
);
|
|
expect(resolveNodeBody).toContain("@requestTimeouts");
|
|
expect(resolveNodeBody).toContain("win-$architecture-zip");
|
|
expect(resolveNodeBody).toContain("node-$($release.version)-win-$architecture.zip");
|
|
});
|
|
|
|
it("persists user-local portable Git for future git-backed updates", () => {
|
|
const portableGitRootBody = extractFunctionBody(source, "Get-PortableGitRoot");
|
|
const portableGitBody = extractFunctionBody(source, "Install-PortableGit");
|
|
const portableArchitectureBody = extractFunctionBody(source, "Get-WindowsPortableArchitecture");
|
|
const portableGitDownloadBody = extractFunctionBody(source, "Resolve-PortableGitDownload");
|
|
const portableGitPathEntriesBody = extractFunctionBody(source, "Get-PortableGitPathEntries");
|
|
const portableGitPathBody = extractFunctionBody(source, "Ensure-PortableGitOnUserPath");
|
|
const usePortableGitBody = extractFunctionBody(source, "Use-PortableGitIfPresent");
|
|
const ensureGitBody = extractFunctionBody(source, "Ensure-Git");
|
|
|
|
expect(portableGitRootBody).toContain("Get-OpenClawDepsRoot");
|
|
expect(portableGitPathEntriesBody).toContain("mingw64\\bin");
|
|
expect(portableGitPathEntriesBody).toContain("usr\\bin");
|
|
expect(portableGitPathEntriesBody).toContain("Split-Path -Parent $gitExe");
|
|
expect(usePortableGitBody).toContain("foreach ($pathEntry in (Get-PortableGitPathEntries))");
|
|
expect(portableGitBody).toContain("Ensure-PortableGitOnUserPath");
|
|
expect(ensureGitBody).toContain("Ensure-PortableGitOnUserPath");
|
|
expect(portableGitPathBody).toContain("Add-ToUserPath $pathEntry");
|
|
expect(portableGitPathBody).toContain("git-backed updates");
|
|
expect(portableArchitectureBody).toContain("Win32_Processor");
|
|
expect(portableArchitectureBody).toContain("Architecture -eq 12");
|
|
expect(portableArchitectureBody).toContain("Win32_ComputerSystem");
|
|
expect(portableArchitectureBody).toContain("PROCESSOR_ARCHITEW6432");
|
|
expect(portableArchitectureBody).toContain("PROCESSOR_ARCHITECTURE");
|
|
expect(portableGitDownloadBody).toContain("Get-WindowsPortableArchitecture");
|
|
expect(portableGitDownloadBody).toContain(
|
|
'Get-WebRequestTimeoutParameters -CommandName "Invoke-RestMethod"',
|
|
);
|
|
expect(portableGitDownloadBody).toContain("@requestTimeouts");
|
|
expect(portableGitBody).toContain("Save-InstallerDownload -Uri $download.Url -OutFile $tmpZip");
|
|
expect(portableGitDownloadBody).toContain("'^MinGit-.*-arm64\\.zip$'");
|
|
expect(portableGitDownloadBody).toContain("'^MinGit-.*-64-bit\\.zip$'");
|
|
expect(portableGitBody).toContain(
|
|
'$tempName = "openclaw-portable-git-" + [guid]::NewGuid().ToString("N")',
|
|
);
|
|
expect(portableGitBody).toContain(
|
|
'Join-Path $script:InstallerTempDirectory ($tempName + ".zip")',
|
|
);
|
|
expect(portableGitBody).toContain("Join-Path $script:InstallerTempDirectory $tempName");
|
|
expect(portableGitBody).toContain(
|
|
"New-Item -ItemType Directory -Force -Path $portableRoot | Out-Null",
|
|
);
|
|
});
|
|
|
|
it("preserves git install budgets and guards with scoped pnpm selection", () => {
|
|
const pnpmVersionBody = extractFunctionBody(source, "Get-RepoPnpmVersion");
|
|
const pnpmVersionMatchBody = extractFunctionBody(source, "Test-PnpmCommandMatchesVersion");
|
|
const ensurePnpmBody = extractFunctionBody(source, "Ensure-Pnpm");
|
|
const gitFilterSupportBody = extractFunctionBody(source, "Test-GitFilterSupport");
|
|
const transactionalCloneBody = extractFunctionBody(source, "New-TransactionalGitCheckout");
|
|
const gitInstallBody = extractFunctionBody(source, "Install-OpenClawFromGit");
|
|
const nodeOptionsBody = extractFunctionBody(source, "Resolve-NodeOptionsWithMinOldSpace");
|
|
const mainBody = extractFunctionBody(source, "Main");
|
|
|
|
expect(pnpmVersionBody).toContain("package.json");
|
|
expect(pnpmVersionBody).toContain(
|
|
"$packageJson.packageManager -match '^pnpm@(?<version>[^+]+)'",
|
|
);
|
|
expect(pnpmVersionMatchBody).toContain("Push-Location -LiteralPath $RepoDir");
|
|
expect(pnpmVersionMatchBody).toContain("$currentVersion.Trim() -eq $PnpmVersion");
|
|
expect(pnpmVersionMatchBody).toContain("} catch {");
|
|
expect(pnpmVersionMatchBody).toContain("return $false");
|
|
expect(ensurePnpmBody).toContain("Get-RepoPnpmVersion -RepoDir $RepoDir");
|
|
expect(ensurePnpmBody).toContain("$pnpmSpec");
|
|
expect(ensurePnpmBody).toContain(
|
|
"Test-PnpmCommandMatchesVersion -PnpmVersion $pnpmVersion -RepoDir $RepoDir -PnpmCommand $pnpmCommand",
|
|
);
|
|
expect(ensurePnpmBody).toContain(
|
|
'@("enable", "--install-directory", $InstallDirectory, "pnpm")',
|
|
);
|
|
expect(ensurePnpmBody).toContain(
|
|
"Invoke-NpmCommand -CommandPath $npmCommand -Arguments $installArgs",
|
|
);
|
|
expect(gitFilterSupportBody).toContain("git clone -h");
|
|
expect(gitFilterSupportBody).toContain("filter");
|
|
expect(transactionalCloneBody).toContain('$cloneArgs += "--filter=blob:none"');
|
|
expect(transactionalCloneBody).toContain("& git @cloneArgs");
|
|
expect(gitInstallBody.indexOf("New-TransactionalGitCheckout")).toBeLessThan(
|
|
gitInstallBody.indexOf("Ensure-Pnpm -RepoDir $RepoDir"),
|
|
);
|
|
expect(gitInstallBody.indexOf("git -C $RepoDir pull --rebase")).toBeLessThan(
|
|
gitInstallBody.indexOf("Ensure-Pnpm -RepoDir $RepoDir"),
|
|
);
|
|
expect(mainBody).toContain("$gitInstallResults = @(Install-OpenClawFromGit");
|
|
expect(mainBody).toContain("Test-BooleanSuccessResult -Results $gitInstallResults");
|
|
expect(mainBody).toContain("$npmInstallResults = @(Install-OpenClaw)");
|
|
expect(mainBody).toContain("Test-BooleanSuccessResult -Results $npmInstallResults");
|
|
expect(gitInstallBody).toContain("Push-Location -LiteralPath $RepoDir");
|
|
expect(gitInstallBody).toContain('$sourceInstallArgs = @("install")');
|
|
expect(gitInstallBody).toContain("Test-ShouldPreferOfflinePnpmInstall -ProjectDir $RepoDir");
|
|
expect(gitInstallBody).toContain('"--config.node-linker=hoisted"');
|
|
expect(gitInstallBody).toContain('"--config.enable-pre-post-scripts=true"');
|
|
expect(gitInstallBody).toContain('"--config.side-effects-cache=false"');
|
|
expect(gitInstallBody).toContain('"--no-frozen-lockfile"');
|
|
expect(gitInstallBody).not.toContain('"--frozen-lockfile"');
|
|
expect(gitInstallBody).not.toContain('"--filter"');
|
|
expect(gitInstallBody).not.toContain('"--ignore-scripts=true"');
|
|
expect(gitInstallBody).toContain(
|
|
'"--config.child-concurrency=$env:PNPM_CONFIG_CHILD_CONCURRENCY"',
|
|
);
|
|
expect(gitInstallBody).toContain(
|
|
'"--config.network-concurrency=$env:PNPM_CONFIG_NETWORK_CONCURRENCY"',
|
|
);
|
|
expect(gitInstallBody).toContain(
|
|
'"--config.workspace-concurrency=$env:PNPM_CONFIG_WORKSPACE_CONCURRENCY"',
|
|
);
|
|
expect(gitInstallBody).toContain("& $pnpmCommand @sourceInstallArgs");
|
|
expect(gitInstallBody).toContain('$env:PNPM_CONFIG_CHILD_CONCURRENCY = "1"');
|
|
expect(gitInstallBody).toContain('$env:PNPM_CONFIG_NETWORK_CONCURRENCY = "4"');
|
|
expect(gitInstallBody).toContain('$env:PNPM_CONFIG_WORKSPACE_CONCURRENCY = "1"');
|
|
expect(gitInstallBody).toContain('$env:PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN = "false"');
|
|
expect(gitInstallBody).toContain('$env:PNPM_CONFIG_SIDE_EFFECTS_CACHE = "false"');
|
|
expect(gitInstallBody).toContain("$installSucceeded = ($LASTEXITCODE -eq 0)");
|
|
expect(gitInstallBody).toContain("clearing node_modules and retrying once");
|
|
expect(gitInstallBody).toContain("Remove-Item -Recurse -Force node_modules");
|
|
expect(gitInstallBody).toContain('Write-Host "[!] pnpm install failed for the Git checkout"');
|
|
expect(gitInstallBody).not.toContain("$pnpmCommand rebuild --pending");
|
|
expect(gitInstallBody).not.toContain("scripts/postinstall-bundled-plugins.mjs");
|
|
expect(gitInstallBody).toContain(
|
|
"$env:NODE_OPTIONS = Resolve-NodeOptionsWithMinOldSpace -NodeOptions $prevNodeOptions -MinOldSpaceMb 8192",
|
|
);
|
|
expect(gitInstallBody).toMatch(/& \$pnpmCommand ui:build\s+if \(\$LASTEXITCODE -ne 0\)/);
|
|
expect(gitInstallBody).not.toContain("if (-not (& $pnpmCommand ui:build))");
|
|
expect(nodeOptionsBody).toContain("--max-old-space-size=$MinOldSpaceMb");
|
|
expect(nodeOptionsBody).toContain("[Math]::Max");
|
|
expect(gitInstallBody).toContain("& $pnpmCommand build");
|
|
expect(gitInstallBody).toContain("$env:NODE_OPTIONS = $prevNodeOptions");
|
|
expect(gitInstallBody).toContain(
|
|
"$env:PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN = $prevPnpmVerifyDepsBeforeRun",
|
|
);
|
|
expect(gitInstallBody).toContain(
|
|
"$env:PNPM_CONFIG_WORKSPACE_CONCURRENCY = $prevPnpmWorkspaceConcurrency",
|
|
);
|
|
expect(gitInstallBody).toContain("Add-ToUserPath $binDir");
|
|
expect(gitInstallBody).toContain('Write-Host "[!] pnpm build failed for the Git checkout"');
|
|
expect(gitInstallBody).toContain('$entryPath = Join-Path $RepoDir "dist\\\\entry.js"');
|
|
expect(gitInstallBody).toContain("Test-Path $entryPath");
|
|
expect(gitInstallBody).toContain('Write-Host "[!] OpenClaw build did not produce $entryPath"');
|
|
expect(gitInstallBody).toContain("node $entryPath --version");
|
|
expect(gitInstallBody).toContain("Format-OpenClawGitWrapper -EntryPath $entryPath");
|
|
expect(gitInstallBody).not.toContain("& $pnpmCommand -C $RepoDir install");
|
|
});
|
|
|
|
it("cleans legacy git submodules only from the selected git checkout", () => {
|
|
const gitInstallBody = extractFunctionBody(source, "Install-OpenClawFromGit");
|
|
const mainBody = extractFunctionBody(source, "Main");
|
|
expect(gitInstallBody).toContain("Remove-LegacySubmodule -RepoDir $RepoDir");
|
|
expect(mainBody).not.toContain("Remove-LegacySubmodule");
|
|
});
|
|
|
|
it("launches interactive onboarding outside Main's captured output", () => {
|
|
const interactiveCommandBody = extractFunctionBody(source, "Invoke-InteractiveOpenClawCommand");
|
|
const mainBody = extractFunctionBody(source, "Main");
|
|
expect(interactiveCommandBody).toContain("Start-Process");
|
|
expect(interactiveCommandBody).toContain("-NoNewWindow");
|
|
expect(interactiveCommandBody).toContain("-Wait");
|
|
expect(interactiveCommandBody).toContain("-PassThru");
|
|
expect(interactiveCommandBody).toContain("$process.ExitCode -ne 0");
|
|
expect(interactiveCommandBody).toContain("failed with exit code");
|
|
expect(mainBody).toContain('Write-Host "Starting setup..." -ForegroundColor Cyan');
|
|
expect(mainBody).toContain("Invoke-InteractiveOpenClawCommand onboard");
|
|
});
|
|
});
|