mirror of
https://github.com/n8n-io/n8n.git
synced 2026-05-31 16:57:08 +02:00
fix(editor): Avoid clearing EULA license key when closing dialog (#22424)
Co-authored-by: Csaba Tuncsik <csaba@n8n.io>
This commit is contained in:
parent
a4d2cfae4a
commit
fe05ea4df8
|
|
@ -257,6 +257,63 @@ describe('SettingsUsageAndPlan', () => {
|
|||
expect(usageStore.activateLicense).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should preserve activation key during EULA flow and send it with acceptance', async () => {
|
||||
usageStore.isLoading = false;
|
||||
usageStore.planName = 'Community';
|
||||
usersStore.currentUser = {
|
||||
globalScopes: ['license:manage'],
|
||||
} as IUser;
|
||||
rbacStore.setGlobalScopes(['license:manage']);
|
||||
usageStore.activateLicense
|
||||
.mockRejectedValueOnce({
|
||||
httpStatusCode: 400,
|
||||
meta: { eulaUrl: 'https://example.com/eula.pdf' },
|
||||
})
|
||||
.mockResolvedValueOnce(undefined);
|
||||
|
||||
const { getByRole, findByTestId } = renderComponent();
|
||||
|
||||
// Open activation modal and enter key
|
||||
await userEvent.click(getByRole('button', { name: /activation/i }));
|
||||
const input = document.querySelector('input') as HTMLInputElement;
|
||||
await userEvent.type(input, 'test-key-123');
|
||||
|
||||
// Click activate - this should trigger EULA modal
|
||||
await userEvent.click(getByRole('button', { name: /activate/i }));
|
||||
|
||||
// EULA modal should appear
|
||||
const eulaModal = await findByTestId('eula-acceptance-modal');
|
||||
expect(eulaModal).toBeInTheDocument();
|
||||
|
||||
// Accept EULA
|
||||
const checkbox = (await findByTestId('eula-checkbox')).querySelector(
|
||||
'input[type="checkbox"]',
|
||||
) as HTMLInputElement;
|
||||
await userEvent.click(checkbox);
|
||||
|
||||
const acceptButton = await findByTestId('eula-accept-button');
|
||||
await userEvent.click(acceptButton);
|
||||
|
||||
// Verify the activation key was preserved and sent with EULA acceptance
|
||||
await waitFor(() => {
|
||||
expect(usageStore.activateLicense).toHaveBeenCalledTimes(2);
|
||||
// First call without EULA
|
||||
expect(usageStore.activateLicense).toHaveBeenNthCalledWith(1, 'test-key-123', undefined);
|
||||
// Second call with EULA URL - key should still be present
|
||||
expect(usageStore.activateLicense).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
'test-key-123',
|
||||
'https://example.com/eula.pdf',
|
||||
);
|
||||
});
|
||||
|
||||
expect(mockToast.showMessage).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: 'success',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should show error when activation fails without EULA requirement', async () => {
|
||||
usageStore.isLoading = false;
|
||||
usageStore.planName = 'Community';
|
||||
|
|
@ -424,5 +481,41 @@ describe('SettingsUsageAndPlan', () => {
|
|||
expect(reopenedInput).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should clear activation key when cancel button is clicked', async () => {
|
||||
usageStore.isLoading = false;
|
||||
usersStore.currentUser = {
|
||||
globalScopes: ['license:manage'],
|
||||
} as IUser;
|
||||
rbacStore.setGlobalScopes(['license:manage']);
|
||||
|
||||
const { getByRole, findByPlaceholderText } = renderComponent();
|
||||
|
||||
await waitAllPromises();
|
||||
|
||||
// Open activation modal
|
||||
await userEvent.click(getByRole('button', { name: /activation/i }));
|
||||
const input = await findByPlaceholderText('Activation key');
|
||||
expect(input).toBeInTheDocument();
|
||||
|
||||
// Enter activation key
|
||||
await userEvent.type(input, 'test-key-should-be-cleared');
|
||||
expect(input).toHaveValue('test-key-should-be-cleared');
|
||||
|
||||
// Click cancel
|
||||
const cancelButton = getByRole('button', { name: /cancel/i });
|
||||
await userEvent.click(cancelButton);
|
||||
|
||||
await waitAllPromises();
|
||||
|
||||
// Reopen modal
|
||||
await userEvent.click(getByRole('button', { name: /activation/i }));
|
||||
|
||||
// Input should be cleared
|
||||
await waitFor(async () => {
|
||||
const reopenedInput = await findByPlaceholderText('Activation key');
|
||||
expect(reopenedInput).toHaveValue('');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -111,9 +111,9 @@ const onLicenseActivation = async (eulaUri?: string) => {
|
|||
} catch (error: unknown) {
|
||||
// Check if error requires EULA acceptance using type guard
|
||||
if (isEulaError(error)) {
|
||||
activationKeyModal.value = false;
|
||||
eulaUrl.value = error.meta.eulaUrl;
|
||||
eulaModal.value = true;
|
||||
activationKeyModal.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -138,6 +138,18 @@ const onEulaCancel = () => {
|
|||
activationKey.value = '';
|
||||
};
|
||||
|
||||
const onActivationCancel = () => {
|
||||
activationKeyModal.value = false;
|
||||
activationKey.value = '';
|
||||
};
|
||||
|
||||
const onActivationModalClose = () => {
|
||||
// Only clear key if not transitioning to EULA flow
|
||||
if (!eulaModal.value) {
|
||||
onActivationCancel();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
documentTitle.set(locale.baseText('settings.usageAndPlan.title'));
|
||||
usageStore.setLoading(true);
|
||||
|
|
@ -187,10 +199,6 @@ const onManagePlan = () => {
|
|||
sendUsageTelemetry('manage_plan');
|
||||
};
|
||||
|
||||
const onDialogClosed = () => {
|
||||
activationKey.value = '';
|
||||
};
|
||||
|
||||
const onDialogOpened = () => {
|
||||
activationKeyInput.value?.focus();
|
||||
};
|
||||
|
|
@ -307,7 +315,7 @@ const openCommunityRegisterModal = () => {
|
|||
top="0"
|
||||
:title="locale.baseText('settings.usageAndPlan.dialog.activation.title')"
|
||||
:modal-class="$style.center"
|
||||
@closed="onDialogClosed"
|
||||
@closed="onActivationModalClose"
|
||||
@opened="onDialogOpened"
|
||||
>
|
||||
<template #default>
|
||||
|
|
@ -318,7 +326,7 @@ const openCommunityRegisterModal = () => {
|
|||
/>
|
||||
</template>
|
||||
<template #footer>
|
||||
<N8nButton type="secondary" @click="activationKeyModal = false">
|
||||
<N8nButton type="secondary" @click="onActivationCancel">
|
||||
{{ locale.baseText('settings.usageAndPlan.dialog.activation.cancel') }}
|
||||
</N8nButton>
|
||||
<N8nButton :disabled="!activationKey" @click="() => onLicenseActivation()">
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user