Collapse advanced first-host install options

This commit is contained in:
rcourtman
2026-03-27 10:42:11 +00:00
parent aa64753fbe
commit 60fb24210a
3 changed files with 251 additions and 163 deletions
@@ -145,8 +145,11 @@ management, and fleet control surfaces.
6. Keep `frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`
oriented around the first monitored host. Install-token generation,
governed command copy, and install instructions belong to the canonical
lifecycle path; transport details and adjacent alternatives must remain
secondary to that first-host onboarding narrative.
lifecycle path; transport details, trust overrides, profile tuning, and
adjacent alternatives must remain secondary to that first-host onboarding
narrative, including an explicit advanced-options disclosure so first-time
operators see token generation, command copy, and status confirmation
before non-default connection controls.
7. Keep `frontend-modern/src/components/Settings/InfrastructureWorkspace.tsx`
and `frontend-modern/src/components/Settings/infrastructureWorkspaceModel.ts`
aligned with that same lifecycle path. Bare infrastructure settings routes
@@ -1,5 +1,5 @@
import type { Component } from 'solid-js';
import { For, Show } from 'solid-js';
import { For, Show, createSignal } from 'solid-js';
import Server from 'lucide-solid/icons/server';
import { ProxmoxIcon } from '@/components/icons/ProxmoxIcon';
import SettingsPanel from '@/components/shared/SettingsPanel';
@@ -22,6 +22,7 @@ import { useInfrastructureOperationsContext } from './useInfrastructureOperation
export const InfrastructureInstallerSection: Component = () => {
const state = useInfrastructureOperationsContext();
const [showAdvancedOptions, setShowAdvancedOptions] = createSignal(false);
return (
<SettingsPanel
@@ -268,134 +269,169 @@ export const InfrastructureInstallerSection: Component = () => {
Installation commands
</h4>
<p class={`mt-0.5 text-xs text-muted ${state.requiresToken() ? 'ml-6' : ''}`}>
The installer auto-detects Docker, Kubernetes, and Proxmox on the target
machine.
Copy the default command for the first host first. Open advanced options only if
this machine needs custom connection or install settings.
</p>
</div>
</div>
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label class="mb-1.5 block text-xs font-medium text-base-content">
Connection URL (Agent → Pulse)
</label>
<div class="flex gap-2">
<input
type="text"
value={state.customAgentUrl()}
onInput={(event) => state.setCustomAgentUrl(event.currentTarget.value)}
placeholder={state.agentUrl()}
class="flex-1 rounded-md border bg-surface px-3 py-1.5 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
/>
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div class="space-y-1">
<p class="text-sm font-semibold text-base-content">
Advanced connection and install options
</p>
<p class="text-xs text-muted">
Default commands use the auto-detected Pulse URL. Open this only if the target
host needs a different URL, custom CA trust, TLS override, command execution,
or a specific install profile.
</p>
</div>
<button
type="button"
onClick={() => setShowAdvancedOptions((current) => !current)}
class="inline-flex items-center justify-center rounded-md border border-border bg-surface px-3 py-2 text-sm font-medium text-base-content transition-colors hover:bg-surface"
>
{showAdvancedOptions()
? 'Hide advanced connection and install options'
: 'Show advanced connection and install options'}
</button>
</div>
<p class="mt-1.5 text-xs text-muted">
Override the address agents use to connect to this server (e.g., use IP address{' '}
<code>http://192.0.2.50:7655</code> if DNS fails).
<Show when={!state.customAgentUrl()}>
<span class="ml-1 opacity-75">Currently using auto-detected: {state.agentUrl()}</span>
</div>
<Show when={showAdvancedOptions()}>
<div class="space-y-3 rounded-md border border-border bg-surface px-4 py-4">
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label class="mb-1.5 block text-xs font-medium text-base-content">
Connection URL (Agent → Pulse)
</label>
<div class="flex gap-2">
<input
type="text"
value={state.customAgentUrl()}
onInput={(event) => state.setCustomAgentUrl(event.currentTarget.value)}
placeholder={state.agentUrl()}
class="flex-1 rounded-md border bg-surface px-3 py-1.5 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
/>
</div>
<p class="mt-1.5 text-xs text-muted">
Override the address agents use to connect to this server (e.g., use IP address{' '}
<code>http://192.0.2.50:7655</code> if DNS fails).
<Show when={!state.customAgentUrl()}>
<span class="ml-1 opacity-75">
Currently using auto-detected: {state.agentUrl()}
</span>
</Show>
</p>
</div>
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label
for="custom-ca-certificate-path"
class="mb-1.5 block text-xs font-medium text-base-content"
>
Custom CA certificate path (optional)
</label>
<div class="flex gap-2">
<input
id="custom-ca-certificate-path"
type="text"
value={state.customCaPath()}
onInput={(event) => state.setCustomCaPath(event.currentTarget.value)}
placeholder={
state.selectedAgentUrl().startsWith('http://')
? 'Not needed for plain HTTP'
: 'Examples: /etc/pulse/ca.pem or C:\\Pulse\\ca.cer'
}
class="flex-1 rounded-md border bg-surface px-3 py-1.5 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
/>
</div>
<p class="mt-1.5 text-xs text-muted">
Preserves custom trust for copied install, upgrade, and uninstall commands.
Shell commands pass <code>--cacert</code> to both the download and the installer.
Windows commands set <code>PULSE_CACERT</code> and use a transport-aware
PowerShell bootstrap for the initial script fetch.
</p>
</div>
<Show when={state.insecureMode()}>
<div class="rounded-md border border-amber-200 bg-amber-50 px-4 py-2 text-sm text-amber-800 dark:border-amber-700 dark:bg-amber-900 dark:text-amber-200">
<span class="font-medium">TLS verification disabled</span> — skip cert checks for
self-signed setups. Not recommended for production.
</div>
</Show>
</p>
</div>
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label
for="custom-ca-certificate-path"
class="mb-1.5 block text-xs font-medium text-base-content"
>
Custom CA certificate path (optional)
</label>
<div class="flex gap-2">
<input
id="custom-ca-certificate-path"
type="text"
value={state.customCaPath()}
onInput={(event) => state.setCustomCaPath(event.currentTarget.value)}
placeholder={
state.selectedAgentUrl().startsWith('http://')
? 'Not needed for plain HTTP'
: 'Examples: /etc/pulse/ca.pem or C:\\Pulse\\ca.cer'
}
class="flex-1 rounded-md border bg-surface px-3 py-1.5 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
/>
</div>
<p class="mt-1.5 text-xs text-muted">
Preserves custom trust for copied install, upgrade, and uninstall commands.
Shell commands pass <code>--cacert</code> to both the download and the installer.
Windows commands set <code>PULSE_CACERT</code> and use a transport-aware
PowerShell bootstrap for the initial script fetch.
</p>
</div>
<label
class="inline-flex cursor-pointer items-center gap-2 text-sm text-base-content"
title="Skip TLS certificate verification (for self-signed certificates)"
>
<input
type="checkbox"
checked={state.insecureMode()}
onChange={(event) => state.setInsecureMode(event.currentTarget.checked)}
class="rounded text-blue-600 focus:ring-blue-500"
/>
Skip TLS certificate verification (self-signed certs; not recommended)
</label>
<Show when={state.insecureMode()}>
<div class="rounded-md border border-amber-200 bg-amber-50 px-4 py-2 text-sm text-amber-800 dark:border-amber-700 dark:bg-amber-900 dark:text-amber-200">
<span class="font-medium">TLS verification disabled</span> — skip cert checks for
self-signed setups. Not recommended for production.
<label
class="inline-flex cursor-pointer items-center gap-2 text-sm text-base-content"
title="Allow Pulse Patrol to execute diagnostic and fix commands on this agent (auto-fix requires Pulse Pro)"
>
<input
type="checkbox"
checked={state.enableCommands()}
onChange={(event) => state.setEnableCommands(event.currentTarget.checked)}
class="rounded text-blue-600 focus:ring-blue-500"
/>
Enable Pulse command execution (for Patrol auto-fix)
</label>
<Show when={state.enableCommands()}>
<div class="rounded-md border border-blue-200 bg-blue-50 px-4 py-2 text-sm text-blue-800 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-200">
<span class="font-medium">Pulse commands enabled</span> — The agent will accept
diagnostic and fix commands from Pulse Patrol features.
</div>
</Show>
<div class="rounded-md border border-emerald-200 bg-emerald-50 px-4 py-2 text-sm text-emerald-900 dark:border-emerald-700 dark:bg-emerald-900 dark:text-emerald-100">
<span class="font-medium">Config signing (optional)</span> — Require signed remote
config payloads with <code>PULSE_AGENT_CONFIG_SIGNATURE_REQUIRED=true</code>.
Provide keys via <code>PULSE_AGENT_CONFIG_SIGNING_KEY</code> (Pulse) and{' '}
<code>PULSE_AGENT_CONFIG_PUBLIC_KEYS</code> (agents).
</div>
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label
for="install-profile-select"
class="mb-1.5 block text-xs font-medium text-base-content"
>
Target profile (optional)
</label>
<select
id="install-profile-select"
value={state.installProfile()}
onChange={(event) =>
state.handleInstallProfileChange(event.currentTarget.value as InstallProfile)
}
class="w-full rounded-md border bg-surface px-3 py-2 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
>
<For each={INSTALL_PROFILE_OPTIONS}>
{(option) => <option value={option.value}>{option.label}</option>}
</For>
</select>
<p class="mt-1.5 text-xs text-muted">
{state.getSelectedInstallProfile().description}
</p>
<Show when={state.getInstallProfileFlags().length > 0}>
<p class="mt-1.5 text-xs text-muted">
Adds flags to shell-based install commands:{' '}
<code>{state.getInstallProfileFlags().join(' ')}</code>
</p>
</Show>
</div>
</div>
</Show>
<label
class="inline-flex cursor-pointer items-center gap-2 text-sm text-base-content"
title="Skip TLS certificate verification (for self-signed certificates)"
>
<input
type="checkbox"
checked={state.insecureMode()}
onChange={(event) => state.setInsecureMode(event.currentTarget.checked)}
class="rounded text-blue-600 focus:ring-blue-500"
/>
Skip TLS certificate verification (self-signed certs; not recommended)
</label>
<label
class="inline-flex cursor-pointer items-center gap-2 text-sm text-base-content"
title="Allow Pulse Patrol to execute diagnostic and fix commands on this agent (auto-fix requires Pulse Pro)"
>
<input
type="checkbox"
checked={state.enableCommands()}
onChange={(event) => state.setEnableCommands(event.currentTarget.checked)}
class="rounded text-blue-600 focus:ring-blue-500"
/>
Enable Pulse command execution (for Patrol auto-fix)
</label>
<Show when={state.enableCommands()}>
<div class="rounded-md border border-blue-200 bg-blue-50 px-4 py-2 text-sm text-blue-800 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-200">
<span class="font-medium">Pulse commands enabled</span> — The agent will accept
diagnostic and fix commands from Pulse Patrol features.
</div>
</Show>
<div class="rounded-md border border-emerald-200 bg-emerald-50 px-4 py-2 text-sm text-emerald-900 dark:border-emerald-700 dark:bg-emerald-900 dark:text-emerald-100">
<span class="font-medium">Config signing (optional)</span> — Require signed remote
config payloads with <code>PULSE_AGENT_CONFIG_SIGNATURE_REQUIRED=true</code>.
Provide keys via <code>PULSE_AGENT_CONFIG_SIGNING_KEY</code> (Pulse) and{' '}
<code>PULSE_AGENT_CONFIG_PUBLIC_KEYS</code> (agents).
</div>
<div class="rounded-md border border-border bg-surface-hover px-4 py-3">
<label for="install-profile-select" class="mb-1.5 block text-xs font-medium text-base-content">
Target profile (optional)
</label>
<select
id="install-profile-select"
value={state.installProfile()}
onChange={(event) =>
state.handleInstallProfileChange(event.currentTarget.value as InstallProfile)
}
class="w-full rounded-md border bg-surface px-3 py-2 text-sm shadow-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500 dark:focus:border-blue-400 dark:focus:ring-blue-800"
>
<For each={INSTALL_PROFILE_OPTIONS}>
{(option) => <option value={option.value}>{option.label}</option>}
</For>
</select>
<p class="mt-1.5 text-xs text-muted">{state.getSelectedInstallProfile().description}</p>
<Show when={state.getInstallProfileFlags().length > 0}>
<p class="mt-1.5 text-xs text-muted">
Adds flags to shell-based install commands:{' '}
<code>{state.getInstallProfileFlags().join(' ')}</code>
</p>
</Show>
</div>
</div>
<div class="space-y-4">
@@ -115,6 +115,10 @@ describe('InfrastructureOperationsController ownership guardrails', () => {
'SettingsAPI.updateSystemSettings',
);
expect(infrastructureInstallerSectionSource).toContain('useInfrastructureOperationsContext');
expect(infrastructureInstallerSectionSource).toContain('Advanced connection and install options');
expect(infrastructureInstallerSectionSource).toContain(
'Show advanced connection and install options',
);
expect(infrastructureInventorySectionSource).toContain('useInfrastructureOperationsContext');
expect(infrastructureStopMonitoringDialogSource).toContain('useInfrastructureOperationsContext');
expect(infrastructureOperationsModelSource).toContain('export const getRowReportingSummary');
@@ -564,6 +568,7 @@ const setupWithResources = (resources: any[], connectedInfrastructure: Connected
};
const getConnectionUrlInput = (): HTMLInputElement => {
openAdvancedInstallOptions();
const urlBlock = screen.getByText(/Connection URL \(Agent → Pulse\)/i).closest('div');
expect(urlBlock).not.toBeNull();
const urlInput = urlBlock?.querySelector('input');
@@ -571,6 +576,35 @@ const getConnectionUrlInput = (): HTMLInputElement => {
return urlInput as HTMLInputElement;
};
const openAdvancedInstallOptions = (): void => {
const toggle = screen.getByRole('button', {
name: /Show advanced connection and install options|Hide advanced connection and install options/i,
});
if ((toggle.textContent ?? '').includes('Show advanced')) {
fireEvent.click(toggle);
}
};
const getCustomCaPathInput = (): HTMLElement => {
openAdvancedInstallOptions();
return screen.getByLabelText(/Custom CA certificate path \(optional\)/i);
};
const getSkipTlsCheckbox = (): HTMLElement => {
openAdvancedInstallOptions();
return screen.getByRole('checkbox', { name: /Skip TLS certificate verification/i });
};
const getEnableCommandsCheckbox = (): HTMLElement => {
openAdvancedInstallOptions();
return screen.getByRole('checkbox', { name: /Enable Pulse command execution/i });
};
const getTargetProfileSelect = (): HTMLElement => {
openAdvancedInstallOptions();
return screen.getByLabelText('Target profile (optional)');
};
beforeEach(() => {
securityStatusResponse = { requiresAuth: true, apiTokenConfigured: false };
navigateMock.mockReset();
@@ -657,6 +691,36 @@ describe('InfrastructureOperationsController token generation', () => {
4000,
);
});
it('keeps advanced connection options collapsed until operators ask for them', async () => {
createTokenMock.mockResolvedValue({
token: 'test-token-123',
record: {
id: 'token-record',
name: 'Test Token',
prefix: 'abcdef',
suffix: '1234',
createdAt: new Date().toISOString(),
},
});
setupComponent();
fireEvent.click(screen.getByRole('button', { name: /Generate token/i }));
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
expect(
screen.getByRole('button', { name: /Show advanced connection and install options/i }),
).toBeInTheDocument();
expect(screen.queryByText(/Connection URL \(Agent → Pulse\)/i)).not.toBeInTheDocument();
openAdvancedInstallOptions();
expect(screen.getByText(/Connection URL \(Agent → Pulse\)/i)).toBeInTheDocument();
expect(
screen.getByRole('button', { name: /Hide advanced connection and install options/i }),
).toBeInTheDocument();
});
});
describe('InfrastructureOperationsController agent lookup', () => {
@@ -1713,12 +1777,11 @@ describe('InfrastructureOperationsController managed agents table', () => {
fireEvent.click(generateButton);
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
openAdvancedInstallOptions();
await waitFor(() => {
expect(
screen.getByRole('checkbox', { name: /Skip TLS certificate verification/i }),
).toBeInTheDocument();
expect(getSkipTlsCheckbox()).toBeInTheDocument();
});
fireEvent.click(screen.getByRole('checkbox', { name: /Skip TLS certificate verification/i }));
fireEvent.click(getSkipTlsCheckbox());
const toggle = screen.getByRole('button', { name: /details for Windows Self-Signed Host/i });
fireEvent.click(toggle);
@@ -2228,11 +2291,11 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
await waitFor(() => {
expect(screen.getByText(/Skip TLS certificate verification/i)).toBeInTheDocument();
expect(getSkipTlsCheckbox()).toBeInTheDocument();
});
// TLS skip is disabled by default
const checkbox = screen.getByRole('checkbox', { name: /Skip TLS certificate verification/i });
const checkbox = getSkipTlsCheckbox();
expect(checkbox).not.toBeChecked();
// Enable it
@@ -2263,10 +2326,10 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
await waitFor(() => {
expect(screen.getByLabelText('Target profile (optional)')).toBeInTheDocument();
expect(getTargetProfileSelect()).toBeInTheDocument();
});
const profileSelect = screen.getByLabelText('Target profile (optional)');
const profileSelect = getTargetProfileSelect();
fireEvent.change(profileSelect, { target: { value: 'proxmox-pbs' } });
expect(trackAgentInstallProfileSelectedMock).toHaveBeenCalledWith(
@@ -2298,10 +2361,10 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
await waitFor(() => {
expect(screen.getByLabelText('Target profile (optional)')).toBeInTheDocument();
expect(getTargetProfileSelect()).toBeInTheDocument();
});
const profileSelect = screen.getByLabelText('Target profile (optional)');
const profileSelect = getTargetProfileSelect();
fireEvent.change(profileSelect, { target: { value: 'proxmox-pbs' } });
const windowsHeading = screen.getByText('Install on Windows');
@@ -2340,10 +2403,10 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
await waitFor(() => {
expect(screen.getByLabelText('Target profile (optional)')).toBeInTheDocument();
expect(getTargetProfileSelect()).toBeInTheDocument();
});
const profileSelect = screen.getByLabelText('Target profile (optional)');
const profileSelect = getTargetProfileSelect();
fireEvent.change(profileSelect, { target: { value: 'docker' } });
expect(trackAgentInstallProfileSelectedMock).toHaveBeenCalledWith(
@@ -2484,15 +2547,13 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
await waitFor(() => {
expect(screen.getByLabelText('Target profile (optional)')).toBeInTheDocument();
expect(getTargetProfileSelect()).toBeInTheDocument();
});
const profileSelect = screen.getByLabelText('Target profile (optional)');
const profileSelect = getTargetProfileSelect();
fireEvent.change(profileSelect, { target: { value: 'docker' } });
const enableCommandsCheckbox = screen.getByRole('checkbox', {
name: /Enable Pulse command execution/i,
});
const enableCommandsCheckbox = getEnableCommandsCheckbox();
fireEvent.click(enableCommandsCheckbox);
const copyButton = screen.getAllByRole('button', { name: /Copy command/i })[0];
@@ -2594,7 +2655,7 @@ describe('InfrastructureOperationsController platform commands', () => {
fireEvent.click(screen.getByRole('button', { name: /Generate token/i }));
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
fireEvent.input(screen.getByLabelText(/Custom CA certificate path \(optional\)/i), {
fireEvent.input(getCustomCaPathInput(), {
target: { value: '/etc/pulse/custom-ca.pem' },
});
@@ -2627,11 +2688,11 @@ describe('InfrastructureOperationsController platform commands', () => {
fireEvent.input(urlInput, {
target: { value: 'http://pulse.example:7655/' },
});
fireEvent.input(screen.getByLabelText(/Custom CA certificate path \(optional\)/i), {
fireEvent.input(getCustomCaPathInput(), {
target: { value: '/etc/pulse/custom-ca.pem' },
});
fireEvent.click(screen.getByRole('checkbox', { name: /Enable Pulse command execution/i }));
fireEvent.change(screen.getByLabelText('Target profile (optional)'), {
fireEvent.click(getEnableCommandsCheckbox());
fireEvent.change(getTargetProfileSelect(), {
target: { value: 'docker' },
});
@@ -2668,12 +2729,12 @@ describe('InfrastructureOperationsController platform commands', () => {
fireEvent.click(screen.getByRole('button', { name: /Generate token/i }));
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
fireEvent.input(screen.getByLabelText(/Custom CA certificate path \(optional\)/i), {
fireEvent.input(getCustomCaPathInput(), {
target: { value: 'C:\\Pulse\\custom-ca.cer' },
});
fireEvent.click(screen.getByRole('checkbox', { name: /Skip TLS certificate verification/i }));
fireEvent.click(screen.getByRole('checkbox', { name: /Enable Pulse command execution/i }));
fireEvent.change(screen.getByLabelText('Target profile (optional)'), {
fireEvent.click(getSkipTlsCheckbox());
fireEvent.click(getEnableCommandsCheckbox());
fireEvent.change(getTargetProfileSelect(), {
target: { value: 'proxmox-pbs' },
});
@@ -2774,14 +2835,10 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
const insecureCheckbox = screen.getByRole('checkbox', {
name: /Skip TLS certificate verification/i,
});
const insecureCheckbox = getSkipTlsCheckbox();
fireEvent.click(insecureCheckbox);
const enableCommandsCheckbox = screen.getByRole('checkbox', {
name: /Enable Pulse command execution/i,
});
const enableCommandsCheckbox = getEnableCommandsCheckbox();
fireEvent.click(enableCommandsCheckbox);
const windowsHeading = screen.getByText('Install on Windows');
@@ -3009,7 +3066,7 @@ describe('InfrastructureOperationsController platform commands', () => {
fireEvent.click(screen.getByRole('button', { name: /Generate token/i }));
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
fireEvent.input(screen.getByLabelText(/Custom CA certificate path \(optional\)/i), {
fireEvent.input(getCustomCaPathInput(), {
target: { value: 'C:\\Pulse\\custom-ca.cer' },
});
@@ -3063,14 +3120,10 @@ describe('InfrastructureOperationsController platform commands', () => {
await waitFor(() => expect(createTokenMock).toHaveBeenCalled(), { interval: 0 });
const insecureCheckbox = screen.getByRole('checkbox', {
name: /Skip TLS certificate verification/i,
});
const insecureCheckbox = getSkipTlsCheckbox();
fireEvent.click(insecureCheckbox);
const enableCommandsCheckbox = screen.getByRole('checkbox', {
name: /Enable Pulse command execution/i,
});
const enableCommandsCheckbox = getEnableCommandsCheckbox();
fireEvent.click(enableCommandsCheckbox);
fireEvent.click(screen.getByRole('button', { name: /details for Windows Upgrade Env/i }));
@@ -3240,10 +3293,6 @@ describe('InfrastructureOperationsController platform commands', () => {
fireEvent.click(screen.getByRole('button', { name: /Confirm without token/i }));
await waitFor(() => {
expect(screen.getByText(/Connection URL \(Agent → Pulse\)/i)).toBeInTheDocument();
});
const urlInput = getConnectionUrlInput();
fireEvent.input(urlInput, {
target: { value: 'http://pulse.example:7655' },
@@ -3276,7 +3325,7 @@ describe('InfrastructureOperationsController platform commands', () => {
});
fireEvent.click(screen.getByRole('button', { name: /Confirm without token/i }));
fireEvent.input(screen.getByLabelText(/Custom CA certificate path \(optional\)/i), {
fireEvent.input(getCustomCaPathInput(), {
target: { value: '/etc/pulse/upgrade-ca.pem' },
});