diff --git a/web/__test__/components/Onboarding/OnboardingCoreSettingsStep.test.ts b/web/__test__/components/Onboarding/OnboardingCoreSettingsStep.test.ts index c8c689566c..0c83638368 100644 --- a/web/__test__/components/Onboarding/OnboardingCoreSettingsStep.test.ts +++ b/web/__test__/components/Onboarding/OnboardingCoreSettingsStep.test.ts @@ -144,6 +144,21 @@ const mountComponent = (props: Record = {}) => { global: { plugins: [createTestI18n()], stubs: { + UInput: { + props: ['modelValue', 'placeholder', 'disabled', 'maxlength', 'tabindex'], + emits: ['update:modelValue'], + template: ` + + `, + }, USelectMenu: { props: ['modelValue', 'items', 'disabled'], emits: ['update:modelValue'], @@ -199,6 +214,17 @@ describe('OnboardingCoreSettingsStep', () => { languagesError.value = null; }); + it('keeps valid server name controls hidden', async () => { + const { wrapper } = mountComponent(); + await flushPromises(); + + const serverNameLabel = wrapper.findAll('label').find((label) => label.text() === 'Server Name'); + const serverNameControl = serverNameLabel?.element.parentElement; + expect(serverNameControl?.classList.contains('hidden')).toBe(true); + expect(serverNameControl?.getAttribute('aria-hidden')).toBe('true'); + expect(wrapper.find('input[placeholder="Tower"]').attributes('tabindex')).toBe('-1'); + }); + it('prefers browser timezone over API on initial setup when draft timezone is empty', async () => { onboardingStore.completed.value = false; @@ -593,7 +619,7 @@ describe('OnboardingCoreSettingsStep', () => { expect(onComplete).toHaveBeenCalledTimes(1); }); - it('blocks submission with invalid server name', async () => { + it('does not block submission with invalid hidden server name', async () => { const { wrapper, onComplete } = mountComponent(); await flushPromises(); @@ -612,8 +638,15 @@ describe('OnboardingCoreSettingsStep', () => { await submitButton.trigger('click'); await flushPromises(); - expect(setCoreSettingsMock).not.toHaveBeenCalled(); - expect(onComplete).not.toHaveBeenCalled(); + expect(setCoreSettingsMock).toHaveBeenCalledWith({ + serverName: 'bad name!', + serverDescription: '', + timeZone: 'UTC', + theme: 'white', + language: 'en_US', + useSsh: false, + }); + expect(onComplete).toHaveBeenCalledTimes(1); }); it('blocks submission with too-long server description', async () => { @@ -768,7 +801,7 @@ describe('OnboardingCoreSettingsStep', () => { expect(onComplete).toHaveBeenCalledTimes(1); }); - it('keeps initialized empty server name invalid even if baseline has a valid name', async () => { + it('uses baseline server name when initialized draft server name is empty', async () => { draftStore.coreSettingsInitialized = true; draftStore.serverName = ''; draftStore.serverDescription = ''; @@ -795,7 +828,14 @@ describe('OnboardingCoreSettingsStep', () => { await submitButton.trigger('click'); await flushPromises(); - expect(setCoreSettingsMock).not.toHaveBeenCalled(); - expect(onComplete).not.toHaveBeenCalled(); + expect(setCoreSettingsMock).toHaveBeenCalledWith({ + serverName: 'TowerBaseline', + serverDescription: '', + timeZone: 'UTC', + theme: 'white', + language: 'en_US', + useSsh: false, + }); + expect(onComplete).toHaveBeenCalledTimes(1); }); }); diff --git a/web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts b/web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts index 32eb5cdf83..1246449bb7 100644 --- a/web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts +++ b/web/__test__/components/Onboarding/OnboardingSummaryStep.test.ts @@ -479,6 +479,13 @@ describe('OnboardingSummaryStep', () => { refetchInstalledPluginsMock.mockResolvedValue(undefined); }); + it('marks the server name hidden in the summary card', () => { + const { wrapper } = mountComponent(); + + const serverNameLabel = wrapper.findAll('span').find((span) => span.text() === 'Server Name'); + expect(serverNameLabel?.element.parentElement?.classList.contains('hidden')).toBe(true); + }); + it.each([ { caseName: 'skips install when plugin is already present', diff --git a/web/src/components/Onboarding/steps/OnboardingCoreSettingsStep.vue b/web/src/components/Onboarding/steps/OnboardingCoreSettingsStep.vue index a70cf8ba4c..b384540d1a 100644 --- a/web/src/components/Onboarding/steps/OnboardingCoreSettingsStep.vue +++ b/web/src/components/Onboarding/steps/OnboardingCoreSettingsStep.vue @@ -355,8 +355,14 @@ const languageItems = computed(() => { }); const isLanguageDisabled = computed(() => isLanguagesLoading.value || !!languagesQueryError.value); +const resolveSubmittedServerName = () => + serverName.value || + coreSettingsResult.value?.server?.name?.trim() || + coreSettingsResult.value?.vars?.name?.trim() || + TRUSTED_DEFAULT_PROFILE.serverName; + const handleSubmit = async () => { - if (serverNameValidation.value || serverDescriptionValidation.value) { + if (serverDescriptionValidation.value) { error.value = t('common.error'); return; } @@ -366,7 +372,7 @@ const handleSubmit = async () => { try { draftStore.setCoreSettings({ - serverName: serverName.value, + serverName: resolveSubmittedServerName(), serverDescription: serverDescription.value, timeZone: selectedTimeZone.value, theme: selectedTheme.value, @@ -441,7 +447,8 @@ const isBusy = computed(() => isSaving.value || (props.isSavingStep ?? false));