From 2decc234b80a2ed3c8666b05f423dc68bb9bdafb Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Wed, 15 Oct 2025 17:46:10 -0400 Subject: [PATCH] feat(activation): enhance plugin installation flow and UI feedback - Updated the `ActivationPluginsStep` component to improve the handling of plugin installations, including better state management for installation completion. - Introduced a new primary action button that dynamically updates based on installation status and selected plugins. - Enhanced unit tests to cover new checkbox interactions and verify the correct behavior of the installation process. - Updated localization files to include new messages related to the installation process. This update significantly improves user experience by providing clearer feedback during plugin installations and ensuring proper state management throughout the process. --- .../Activation/ActivationPluginsStep.test.ts | 28 ++++++++- .../Activation/ActivationPluginsStep.vue | 58 +++++++++++++++---- web/src/locales/en.json | 1 + 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/web/__test__/components/Activation/ActivationPluginsStep.test.ts b/web/__test__/components/Activation/ActivationPluginsStep.test.ts index c3d42dc07..2975a6ea6 100644 --- a/web/__test__/components/Activation/ActivationPluginsStep.test.ts +++ b/web/__test__/components/Activation/ActivationPluginsStep.test.ts @@ -65,6 +65,14 @@ describe('ActivationPluginsStep', () => { const { wrapper, props } = mountComponent(); + const checkboxes = wrapper.findAll('input[type="checkbox"]'); + for (const checkbox of checkboxes) { + const input = checkbox.element as HTMLInputElement; + input.checked = true; + await checkbox.trigger('change'); + } + await flushPromises(); + const installButton = wrapper .findAll('[data-testid="brand-button"]') .find((button) => button.text().includes('Install')); @@ -76,15 +84,33 @@ describe('ActivationPluginsStep', () => { const firstCallArgs = installPluginMock.mock.calls[0]?.[0]; expect(firstCallArgs?.forced).toBe(true); expect(firstCallArgs?.url).toContain('community.applications'); - expect(props.onComplete).toHaveBeenCalled(); + expect(props.onComplete).not.toHaveBeenCalled(); expect(wrapper.html()).toContain('installation started'); expect(wrapper.html()).toContain('installed successfully'); + + const continueButton = wrapper + .findAll('[data-testid="brand-button"]') + .find((button) => button.text().includes('Continue')); + expect(continueButton).toBeTruthy(); + const callsBeforeContinue = props.onComplete.mock.calls.length; + await continueButton!.trigger('click'); + + expect(props.onComplete.mock.calls.length).toBeGreaterThanOrEqual(callsBeforeContinue + 1); }); it('shows error message when installation fails', async () => { installPluginMock.mockRejectedValueOnce(new Error('install failed')); const { wrapper, props } = mountComponent(); + + const errorCheckboxes = wrapper.findAll('input[type="checkbox"]'); + for (const checkbox of errorCheckboxes) { + const input = checkbox.element as HTMLInputElement; + input.checked = true; + await checkbox.trigger('change'); + } + await flushPromises(); + const installButton = wrapper .findAll('[data-testid="brand-button"]') .find((button) => button.text().includes('Install')); diff --git a/web/src/components/Activation/ActivationPluginsStep.vue b/web/src/components/Activation/ActivationPluginsStep.vue index 56a6362af..68cdfe487 100644 --- a/web/src/components/Activation/ActivationPluginsStep.vue +++ b/web/src/components/Activation/ActivationPluginsStep.vue @@ -1,5 +1,5 @@