mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(editor): Remove Trial logic in personalization modal and port to script setup (#10649)
Co-authored-by: Csaba Tuncsik <csaba.tuncsik@gmail.com>
This commit is contained in:
parent
36177b0943
commit
f114035a6b
157
packages/editor-ui/src/components/PersonalizationModal.test.ts
Normal file
157
packages/editor-ui/src/components/PersonalizationModal.test.ts
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
import { createComponentRenderer } from '@/__tests__/render';
|
||||||
|
import { getDropdownItems, mockedStore } from '@/__tests__/utils';
|
||||||
|
import { createUser } from '@/__tests__/data/users';
|
||||||
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
|
import PersonalizationModal from '@/components/PersonalizationModal.vue';
|
||||||
|
import { useUsersStore } from '@/stores/users.store';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import {
|
||||||
|
COMPANY_TYPE_KEY,
|
||||||
|
EMAIL_KEY,
|
||||||
|
COMPANY_INDUSTRY_EXTENDED_KEY,
|
||||||
|
OTHER_COMPANY_INDUSTRY_EXTENDED_KEY,
|
||||||
|
MARKETING_AUTOMATION_GOAL_KEY,
|
||||||
|
OTHER_MARKETING_AUTOMATION_GOAL_KEY,
|
||||||
|
ROLE_KEY,
|
||||||
|
ROLE_OTHER_KEY,
|
||||||
|
DEVOPS_AUTOMATION_GOAL_OTHER_KEY,
|
||||||
|
DEVOPS_AUTOMATION_GOAL_KEY,
|
||||||
|
} from '@/constants';
|
||||||
|
|
||||||
|
const renderModal = createComponentRenderer(PersonalizationModal, {
|
||||||
|
global: {
|
||||||
|
stubs: {
|
||||||
|
Modal: {
|
||||||
|
template: `
|
||||||
|
<div>
|
||||||
|
<slot name="header" />
|
||||||
|
<slot name="title" />
|
||||||
|
<slot name="content" />
|
||||||
|
<slot name="footer" />
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('PersonalizationModal', () => {
|
||||||
|
it('mounts', () => {
|
||||||
|
const { getByTitle } = renderModal({ pinia: createTestingPinia() });
|
||||||
|
expect(getByTitle('Customize n8n to you')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows user input when needed for desktop deployment', () => {
|
||||||
|
const pinia = createTestingPinia();
|
||||||
|
const usersStore = mockedStore(useUsersStore);
|
||||||
|
usersStore.currentUser = createUser({ firstName: undefined });
|
||||||
|
|
||||||
|
const settingsStore = mockedStore(useSettingsStore);
|
||||||
|
settingsStore.isDesktopDeployment = true;
|
||||||
|
|
||||||
|
const { getByTestId } = renderModal({ pinia });
|
||||||
|
expect(getByTestId(EMAIL_KEY)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Company field', () => {
|
||||||
|
it('allows completion of company related fields', async () => {
|
||||||
|
const { getByTestId } = renderModal({ pinia: createTestingPinia() });
|
||||||
|
|
||||||
|
const companyTypeSelect = getByTestId(COMPANY_TYPE_KEY);
|
||||||
|
|
||||||
|
const otherTypeOfCompanyOption = [...(await getDropdownItems(companyTypeSelect))].find(
|
||||||
|
(node) => node.textContent === 'Other',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(otherTypeOfCompanyOption);
|
||||||
|
|
||||||
|
const industrySelect = getByTestId(COMPANY_INDUSTRY_EXTENDED_KEY);
|
||||||
|
expect(industrySelect).toBeInTheDocument();
|
||||||
|
|
||||||
|
const otherIndustryOption = [...(await getDropdownItems(industrySelect))].find(
|
||||||
|
(node) => node.textContent === 'Other (please specify)',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(otherIndustryOption);
|
||||||
|
|
||||||
|
expect(getByTestId(OTHER_COMPANY_INDUSTRY_EXTENDED_KEY)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows only company and source select when not used for work', async () => {
|
||||||
|
const { getByTestId, baseElement } = renderModal({ pinia: createTestingPinia() });
|
||||||
|
|
||||||
|
const companyTypeSelect = getByTestId(COMPANY_TYPE_KEY);
|
||||||
|
|
||||||
|
const nonWorkOption = [...(await getDropdownItems(companyTypeSelect))].find(
|
||||||
|
(node) => node.textContent === "I'm not using n8n for work",
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(nonWorkOption);
|
||||||
|
|
||||||
|
expect(baseElement.querySelectorAll('input').length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows completion of role related fields', async () => {
|
||||||
|
const { getByTestId, queryByTestId } = renderModal({ pinia: createTestingPinia() });
|
||||||
|
|
||||||
|
const roleSelect = getByTestId(ROLE_KEY);
|
||||||
|
const roleItems = [...(await getDropdownItems(roleSelect))];
|
||||||
|
|
||||||
|
const devOps = roleItems.find((node) => node.textContent === 'Devops') as Element;
|
||||||
|
const engineering = roleItems.find((node) => node.textContent === 'Engineering') as Element;
|
||||||
|
const it = roleItems.find((node) => node.textContent === 'IT') as Element;
|
||||||
|
const other = roleItems.find(
|
||||||
|
(node) => node.textContent === 'Other (please specify)',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(devOps);
|
||||||
|
const automationGoalSelect = getByTestId(DEVOPS_AUTOMATION_GOAL_KEY);
|
||||||
|
expect(automationGoalSelect).toBeInTheDocument();
|
||||||
|
|
||||||
|
await userEvent.click(engineering);
|
||||||
|
expect(automationGoalSelect).toBeInTheDocument();
|
||||||
|
|
||||||
|
await userEvent.click(it);
|
||||||
|
expect(automationGoalSelect).toBeInTheDocument();
|
||||||
|
|
||||||
|
const otherGoalsItem = [...(await getDropdownItems(automationGoalSelect))].find(
|
||||||
|
(node) => node.textContent === 'Other',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(otherGoalsItem);
|
||||||
|
expect(getByTestId(DEVOPS_AUTOMATION_GOAL_OTHER_KEY)).toBeInTheDocument();
|
||||||
|
|
||||||
|
await userEvent.click(other);
|
||||||
|
expect(queryByTestId(DEVOPS_AUTOMATION_GOAL_KEY)).not.toBeInTheDocument();
|
||||||
|
expect(getByTestId(ROLE_OTHER_KEY)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('allows completion of marketing and sales related fields', async () => {
|
||||||
|
const { getByTestId } = renderModal({ pinia: createTestingPinia() });
|
||||||
|
|
||||||
|
const companyTypeSelect = getByTestId(COMPANY_TYPE_KEY);
|
||||||
|
|
||||||
|
const anyWorkOption = [...(await getDropdownItems(companyTypeSelect))].find(
|
||||||
|
(node) => node.textContent !== "I'm not using n8n for work",
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(anyWorkOption);
|
||||||
|
|
||||||
|
const roleSelect = getByTestId(ROLE_KEY);
|
||||||
|
const salesAndMarketingOption = [...(await getDropdownItems(roleSelect))].find(
|
||||||
|
(node) => node.textContent === 'Sales and Marketing',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(salesAndMarketingOption);
|
||||||
|
|
||||||
|
const salesAndMarketingSelect = getByTestId(MARKETING_AUTOMATION_GOAL_KEY);
|
||||||
|
const otherItem = [...(await getDropdownItems(salesAndMarketingSelect))].find(
|
||||||
|
(node) => node.textContent === 'Other',
|
||||||
|
) as Element;
|
||||||
|
|
||||||
|
await userEvent.click(otherItem);
|
||||||
|
expect(getByTestId(OTHER_MARKETING_AUTOMATION_GOAL_KEY)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load diff
|
@ -1,144 +0,0 @@
|
||||||
import PersonalizationModal from '@/components/PersonalizationModal.vue';
|
|
||||||
import { createTestingPinia } from '@pinia/testing';
|
|
||||||
import userEvent from '@testing-library/user-event';
|
|
||||||
import { PERSONALIZATION_MODAL_KEY, ROLE, STORES, VIEWS } from '@/constants';
|
|
||||||
import { cleanupAppModals, createAppModals, retry } from '@/__tests__/utils';
|
|
||||||
import { createComponentRenderer } from '@/__tests__/render';
|
|
||||||
import { fireEvent } from '@testing-library/vue';
|
|
||||||
import { useUsersStore } from '@/stores/users.store';
|
|
||||||
import { useUsageStore } from '@/stores/usage.store';
|
|
||||||
|
|
||||||
const pinia = createTestingPinia({
|
|
||||||
initialState: {
|
|
||||||
[STORES.UI]: {
|
|
||||||
modalsById: {
|
|
||||||
[PERSONALIZATION_MODAL_KEY]: { open: true },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[STORES.SETTINGS]: {
|
|
||||||
settings: {
|
|
||||||
templates: {
|
|
||||||
host: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
[STORES.USERS]: {
|
|
||||||
usersById: {
|
|
||||||
123: {
|
|
||||||
email: 'john@doe.com',
|
|
||||||
firstName: 'John',
|
|
||||||
lastName: 'Doe',
|
|
||||||
isDefaultUser: false,
|
|
||||||
isPendingUser: false,
|
|
||||||
role: ROLE.Owner,
|
|
||||||
mfaEnabled: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
currentUserId: '123',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const renderComponent = createComponentRenderer(PersonalizationModal, {
|
|
||||||
props: {
|
|
||||||
teleported: false,
|
|
||||||
appendToBody: false,
|
|
||||||
},
|
|
||||||
pinia,
|
|
||||||
global: {
|
|
||||||
mocks: {
|
|
||||||
$route: {
|
|
||||||
name: VIEWS.HOMEPAGE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('PersonalizationModal.vue', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
createAppModals();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
cleanupAppModals();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render correctly', async () => {
|
|
||||||
const { getByTestId } = renderComponent();
|
|
||||||
|
|
||||||
await retry(() => expect(getByTestId('personalization-form')).toBeInTheDocument());
|
|
||||||
|
|
||||||
const modalContent = getByTestId('personalization-form');
|
|
||||||
expect(modalContent.querySelectorAll('.n8n-select').length).toEqual(5);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display new option when role is "Devops", "Engineering", "IT", or "Sales and marketing"', async () => {
|
|
||||||
const { getByTestId } = renderComponent();
|
|
||||||
|
|
||||||
await retry(() => expect(getByTestId('personalization-form')).toBeInTheDocument());
|
|
||||||
|
|
||||||
for (const index of [3, 4, 5, 6]) {
|
|
||||||
const modalContent = getByTestId('personalization-form');
|
|
||||||
const expectFn = expect; // So we don't break @typescript-eslint/no-loop-func
|
|
||||||
const select = modalContent.querySelectorAll('.n8n-select')[1];
|
|
||||||
|
|
||||||
await fireEvent.click(select);
|
|
||||||
|
|
||||||
const item = select.querySelectorAll('.el-select-dropdown__item')[index];
|
|
||||||
|
|
||||||
await fireEvent.click(item);
|
|
||||||
|
|
||||||
await retry(() => {
|
|
||||||
expectFn(modalContent.querySelectorAll('.n8n-select').length).toEqual(6);
|
|
||||||
expectFn(modalContent.querySelector('[name^="automationGoal"]')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display self serve trial option when company size is larger than 500', async () => {
|
|
||||||
const { getByTestId } = renderComponent();
|
|
||||||
|
|
||||||
await retry(() => expect(getByTestId('personalization-form')).toBeInTheDocument());
|
|
||||||
|
|
||||||
const modalContent = getByTestId('personalization-form');
|
|
||||||
|
|
||||||
const select = modalContent.querySelectorAll('.n8n-select')[3];
|
|
||||||
await fireEvent.click(select);
|
|
||||||
|
|
||||||
const item = select.querySelectorAll('.el-select-dropdown__item')[3];
|
|
||||||
await fireEvent.click(item);
|
|
||||||
|
|
||||||
await retry(() => {
|
|
||||||
expect(modalContent.querySelector('.card')).not.toBeNull();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display send telemetry when requesting enterprise trial', async () => {
|
|
||||||
const usersStore = useUsersStore(pinia);
|
|
||||||
vi.spyOn(usersStore, 'submitPersonalizationSurvey').mockResolvedValue();
|
|
||||||
|
|
||||||
const usageStore = useUsageStore(pinia);
|
|
||||||
const spyLicenseTrial = vi.spyOn(usageStore, 'requestEnterpriseLicenseTrial');
|
|
||||||
|
|
||||||
const { getByTestId, getByRole } = renderComponent();
|
|
||||||
|
|
||||||
await retry(() => expect(getByTestId('personalization-form')).toBeInTheDocument());
|
|
||||||
|
|
||||||
const modalContent = getByTestId('personalization-form');
|
|
||||||
|
|
||||||
const select = modalContent.querySelectorAll('.n8n-select')[3];
|
|
||||||
await fireEvent.click(select);
|
|
||||||
|
|
||||||
const item = select.querySelectorAll('.el-select-dropdown__item')[3];
|
|
||||||
await fireEvent.click(item);
|
|
||||||
|
|
||||||
const agreeCheckbox = modalContent.querySelector('.n8n-checkbox');
|
|
||||||
assert(agreeCheckbox);
|
|
||||||
await fireEvent.click(agreeCheckbox);
|
|
||||||
|
|
||||||
const submitButton = getByRole('button');
|
|
||||||
await userEvent.click(submitButton);
|
|
||||||
|
|
||||||
await retry(() => expect(spyLicenseTrial).toHaveBeenCalled());
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in a new issue