mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Collapse advanced first-host install options
This commit is contained in:
@@ -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">
|
||||
|
||||
+92
-43
@@ -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' },
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user