Compare commits

...
Author SHA1 Message Date
paseo-bot[bot]andthecardcheat 48e5a69845 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 <pitt.joshua.miller@gmail.com>
2026-09-28 18:57:08 +02:00
3 changed files with 58 additions and 7 deletions
@@ -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,
}) => {
@@ -253,6 +253,19 @@ export async function fillDirectHostUri(page: Page, uri: string): Promise<void>
await page.getByTestId("direct-host-uri-input").fill(uri);
}
export async function fillDirectHostFields(
page: Page,
fields: { host: string; port: string },
): Promise<void> {
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<void> {
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 },
+13 -7
View File
@@ -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;