Files
kandev/apps/web/e2e/tests/ssh/trust-gate.spec.ts
T
José Almeida c2a9781f65 test(e2e): restore the seeded executor's pinned fingerprint after R5
The fingerprint-change-warning spec pinned a deliberately bogus
fingerprint on the worker's seeded SSH executor to exercise the
mismatch UI, then exited without resetting it. Later specs in the
same worker that launched real tasks against the same executor
(workdir-per-profile R1/R2 in alphabetical order) failed at SSH dial
time with host-key-changed, since the executor was still pinned to
the bad value.

Wrap the assertion in a try/finally that restores the original
fingerprint from seedData when the test ends, so the worker leaves
the executor in the same state it inherited.
2026-05-18 00:05:15 +01:00

114 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test, expect } from "../../fixtures/ssh-test-base";
import { SSHSettingsPage } from "../../pages/SSHSettingsPage";
/**
* The defining UX guarantee of the SSH executor: Save is locked until the
* user explicitly trusts the fingerprint they just observed, editing any
* field that could reach a different machine resets that trust, and
* fingerprint-change between trust and save is called out in the UI.
*
* Covers e2e-plan.md group C (C1–C7).
*/
test.describe("ssh trust gate", () => {
test("save disabled until trust ticked even after a successful test", async ({
testPage,
seedData,
}) => {
const page = new SSHSettingsPage(testPage);
await page.gotoNew();
await page.fillForm({
name: "C1",
host: seedData.sshTarget.host,
port: seedData.sshTarget.port,
user: seedData.sshTarget.user,
identitySource: "file",
identityFile: seedData.sshTarget.identityFile,
});
await page.clickTest();
await page.waitForTestResult();
await expect(page.saveButton).toBeDisabled();
await page.tickTrust();
await expect(page.saveButton).toBeEnabled();
});
for (const field of [
{ name: "host", apply: (p: SSHSettingsPage) => p.fillForm({ host: "other.example.com" }) },
{ name: "port", apply: (p: SSHSettingsPage) => p.fillForm({ port: 2222 }) },
{ name: "user", apply: (p: SSHSettingsPage) => p.fillForm({ user: "root" }) },
{
name: "identity_source",
apply: (p: SSHSettingsPage) => p.fillForm({ identitySource: "agent" }),
},
]) {
test(`editing ${field.name} after a test clears the result and unticks trust`, async ({
testPage,
seedData,
}) => {
const page = new SSHSettingsPage(testPage);
await page.gotoNew();
await page.fillForm({
name: `C-edit-${field.name}`,
host: seedData.sshTarget.host,
port: seedData.sshTarget.port,
user: seedData.sshTarget.user,
identitySource: "file",
identityFile: seedData.sshTarget.identityFile,
});
await page.clickTest();
await page.waitForTestResult();
await page.tickTrust();
await expect(page.saveButton).toBeEnabled();
await field.apply(page);
await expect(page.saveButton).toBeDisabled();
await expect(page.trustCheckbox).not.toBeChecked();
});
}
// C7 — fingerprint-change warning when re-testing with already-pinned
// fingerprint differing from the new one. We simulate by editing the
// executor's pinned fingerprint via the API and reloading the form.
test("fingerprint-change warning surfaces when observed fingerprint differs from pinned", async ({
testPage,
apiClient,
seedData,
}) => {
// Set a wrong fingerprint on the seeded executor. Restore it after the
// test so any later spec in the worker that exercises a real launch
// doesn't trip over host-key-changed against the still-bad pin.
const originalFingerprint = seedData.sshTarget.hostFingerprint;
await apiClient.updateExecutor(seedData.sshExecutorId, {
config: {
ssh_host: seedData.sshTarget.host,
ssh_port: String(seedData.sshTarget.port),
ssh_user: seedData.sshTarget.user,
ssh_identity_source: "file",
ssh_identity_file: seedData.sshTarget.identityFile,
ssh_host_fingerprint: "SHA256:wrong-fingerprint-on-purpose",
},
});
try {
const page = new SSHSettingsPage(testPage);
await page.gotoExisting(seedData.sshExecutorId);
await expect(page.pinnedFingerprint()).toHaveText("SHA256:wrong-fingerprint-on-purpose");
await page.clickTest();
await page.waitForTestResult();
await expect(page.fingerprintChangeWarning()).toBeVisible();
await expect(page.observedFingerprint()).toHaveText(seedData.sshTarget.hostFingerprint);
} finally {
await apiClient.updateExecutor(seedData.sshExecutorId, {
config: {
ssh_host: seedData.sshTarget.host,
ssh_port: String(seedData.sshTarget.port),
ssh_user: seedData.sshTarget.user,
ssh_identity_source: "file",
ssh_identity_file: seedData.sshTarget.identityFile,
ssh_host_fingerprint: originalFingerprint,
},
});
}
});
});