From 48e5a69845b7cc5144a6f4796480884aeb083435 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 18:57:08 +0200 Subject: [PATCH] Connect to the open Advanced URI in Direct connection With Advanced open, Connect built the connection from the Host and Port fields and ignored a tcp:// URI in the Advanced field. A blank Host failed with "Host is required", and an edited URI connected to the address the fields still held. Connect now uses the URI shown while Advanced is open; the Password field still supplies a password the URI does not carry. Closes #5495 Co-authored-by: thecardcheat --- .../e2e/browser/settings-navigation.spec.ts | 32 +++++++++++++++++++ packages/app/e2e/support/helpers/settings.ts | 13 ++++++++ .../app/src/components/add-host-modal.tsx | 20 ++++++++---- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/packages/app/e2e/browser/settings-navigation.spec.ts b/packages/app/e2e/browser/settings-navigation.spec.ts index bc8e1eedec..8224132d71 100644 --- a/packages/app/e2e/browser/settings-navigation.spec.ts +++ b/packages/app/e2e/browser/settings-navigation.spec.ts @@ -27,6 +27,8 @@ import { openCompactSettingsHost, expectAddHostMethodOptions, fillDirectHostUri, + fillDirectHostFields, + connectDirectHost, expectDirectHostFormValues, expectDirectHostSslEnabled, expectDirectHostUriValue, @@ -112,6 +114,36 @@ test.describe("Settings sidebar navigation", () => { await expectDirectHostUriHidden(page); }); + test("direct connection connects to the open Advanced URI when Host is blank", async ({ + page, + }) => { + await gotoAppShell(page); + await openSettings(page); + await openAddHostFlow(page); + await selectHostConnectionType(page, "direct"); + + await toggleHostAdvanced(page); + await fillDirectHostUri(page, `tcp://127.0.0.1:${getE2EDaemonPort()}`); + + await connectDirectHost(page); + }); + + test("direct connection connects to an edited Advanced URI instead of the fields", async ({ + page, + }) => { + await gotoAppShell(page); + await openSettings(page); + await openAddHostFlow(page); + await selectHostConnectionType(page, "direct"); + + await fillDirectHostFields(page, { host: "127.0.0.1", port: "9" }); + await toggleHostAdvanced(page); + await expectDirectHostUriValue(page, "tcp://127.0.0.1:9"); + await fillDirectHostUri(page, `tcp://127.0.0.1:${getE2EDaemonPort()}`); + + await connectDirectHost(page); + }); + test("Escape lets settings dropdowns and modals close before leaving settings", async ({ page, }) => { diff --git a/packages/app/e2e/support/helpers/settings.ts b/packages/app/e2e/support/helpers/settings.ts index 1702f7fe44..db0f0b3bd3 100644 --- a/packages/app/e2e/support/helpers/settings.ts +++ b/packages/app/e2e/support/helpers/settings.ts @@ -253,6 +253,19 @@ export async function fillDirectHostUri(page: Page, uri: string): Promise await page.getByTestId("direct-host-uri-input").fill(uri); } +export async function fillDirectHostFields( + page: Page, + fields: { host: string; port: string }, +): Promise { + await page.getByTestId("direct-host-input").fill(fields.host); + await page.getByTestId("direct-port-input").fill(fields.port); +} + +export async function connectDirectHost(page: Page): Promise { + await page.getByTestId("direct-host-submit").click(); + await expect(page.getByTestId("add-host-modal")).toHaveCount(0, { timeout: 30_000 }); +} + export async function expectDirectHostFormValues( page: Page, fields: { host: string; port: string; password: string }, diff --git a/packages/app/src/components/add-host-modal.tsx b/packages/app/src/components/add-host-modal.tsx index b388d76047..fb81d73d12 100644 --- a/packages/app/src/components/add-host-modal.tsx +++ b/packages/app/src/components/add-host-modal.tsx @@ -195,6 +195,12 @@ function draftFromConnectionUri(uri: string): DirectConnectionDraft { }; } +// The Password field stays visible under Advanced, so it fills in a URI that carries none. +function draftFromAdvancedUri(uri: string, fieldPassword: string): DirectConnectionDraft { + const draft = draftFromConnectionUri(uri); + return draft.password ? draft : { ...draft, password: fieldPassword }; +} + function normalizeTransportMessage(message: string | null | undefined): string | null { if (!message) return null; const trimmed = message.trim(); @@ -405,18 +411,18 @@ export function AddHostModal({ visible, onClose, onCancel, onSaved }: AddHostMod const handleSave = useCallback(async () => { if (isSaving) return; - const relayUri = isAdvancedOpen ? advancedUri.trim() : ""; - if (relayUri.startsWith("relay://") || relayUri.includes("#connect=")) { - await handleSaveRelay(relayUri); + const advancedInput = isAdvancedOpen ? advancedUri.trim() : ""; + if (advancedInput.startsWith("relay://") || advancedInput.includes("#connect=")) { + await handleSaveRelay(advancedInput); return; } let connection: PreparedDirectConnection; try { - connection = prepareDirectConnection( - { host, port, useTls, password }, - directConnectionLabels, - ); + const draft = advancedInput + ? draftFromAdvancedUri(advancedInput, password) + : { host, port, useTls, password }; + connection = prepareDirectConnection(draft, directConnectionLabels); } catch (error) { const message = error instanceof Error ? error.message : directConnectionLabels.invalidConnection;