debian-mirror-gitlab/spec/frontend/super_sidebar/components/user_menu_spec.js
2023-05-27 22:25:52 +05:30

375 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { GlAvatar, GlDisclosureDropdown } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import UserMenu from '~/super_sidebar/components/user_menu.vue';
import UserNameGroup from '~/super_sidebar/components/user_name_group.vue';
import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
import invalidUrl from '~/lib/utils/invalid_url';
import { mockTracking } from 'helpers/tracking_helper';
import PersistentUserCallout from '~/persistent_user_callout';
import { userMenuMockData, userMenuMockStatus, userMenuMockPipelineMinutes } from '../mock_data';
describe('UserMenu component', () => {
let wrapper;
let trackingSpy;
const GlEmoji = { template: '<img/>' };
const toggleNewNavEndpoint = invalidUrl;
const showDropdown = () => wrapper.findComponent(GlDisclosureDropdown).vm.$emit('shown');
const createWrapper = (userDataChanges = {}) => {
wrapper = mountExtended(UserMenu, {
propsData: {
data: {
...userMenuMockData,
...userDataChanges,
},
},
stubs: {
GlEmoji,
GlAvatar: true,
},
provide: {
toggleNewNavEndpoint,
},
});
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
};
describe('Toggle button', () => {
let toggle;
beforeEach(() => {
createWrapper();
toggle = wrapper.findByTestId('base-dropdown-toggle');
});
it('renders User Avatar in a toggle', () => {
const avatar = toggle.findComponent(GlAvatar);
expect(avatar.exists()).toBe(true);
expect(avatar.props()).toMatchObject({
entityName: userMenuMockData.name,
src: userMenuMockData.avatar_url,
});
});
it('renders screen reader text', () => {
expect(toggle.find('.gl-sr-only').text()).toBe(`${userMenuMockData.name} users menu`);
});
});
describe('User Menu Group', () => {
it('renders and passes data to it', () => {
createWrapper();
const userNameGroup = wrapper.findComponent(UserNameGroup);
expect(userNameGroup.exists()).toBe(true);
expect(userNameGroup.props('user')).toEqual(userMenuMockData);
});
});
describe('User status item', () => {
let item;
const setItem = ({ can_update, busy, customized } = {}) => {
createWrapper({ status: { ...userMenuMockStatus, can_update, busy, customized } });
item = wrapper.findByTestId('status-item');
};
describe('When user cannot update the status', () => {
it('does not render the status menu item', () => {
setItem();
expect(item.exists()).toBe(false);
});
});
describe('When user can update the status', () => {
it('renders the status menu item', () => {
setItem({ can_update: true });
expect(item.exists()).toBe(true);
});
it('should set the CSS class for triggering status update modal', () => {
setItem({ can_update: true });
expect(item.find('.js-set-status-modal-trigger').exists()).toBe(true);
});
describe('renders correct label', () => {
it.each`
busy | customized | label
${false} | ${false} | ${'Set status'}
${false} | ${true} | ${'Edit status'}
${true} | ${false} | ${'Edit status'}
${true} | ${true} | ${'Edit status'}
`(
'when busy is "$busy" and customized is "$customized" the label is "$label"',
({ busy, customized, label }) => {
setItem({ can_update: true, busy, customized });
expect(item.text()).toBe(label);
},
);
});
describe('Status update modal wrapper', () => {
const findModalWrapper = () => wrapper.find('.js-set-status-modal-wrapper');
it('renders the modal wrapper', () => {
setItem({ can_update: true });
expect(findModalWrapper().exists()).toBe(true);
});
it('sets default data attributes when status is not customized', () => {
setItem({ can_update: true });
expect(findModalWrapper().attributes()).toMatchObject({
'data-current-emoji': '',
'data-current-message': '',
'data-default-emoji': 'speech_balloon',
});
});
it('sets user status as data attributes when status is customized', () => {
setItem({ can_update: true, customized: true });
expect(findModalWrapper().attributes()).toMatchObject({
'data-current-emoji': userMenuMockStatus.emoji,
'data-current-message': userMenuMockStatus.message,
'data-current-availability': userMenuMockStatus.availability,
'data-current-clear-status-after': userMenuMockStatus.clear_after,
});
});
});
});
});
describe('Start Ultimate trial item', () => {
let item;
const setItem = ({ has_start_trial } = {}) => {
createWrapper({ trial: { has_start_trial } });
item = wrapper.findByTestId('start-trial-item');
};
describe('When Ultimate trial is not suggested for the user', () => {
it('does not render the start trial menu item', () => {
setItem();
expect(item.exists()).toBe(false);
});
});
describe('When Ultimate trial can be suggested for the user', () => {
it('does render the start trial menu item', () => {
setItem({ has_start_trial: true });
expect(item.exists()).toBe(true);
});
});
});
describe('Buy Pipeline Minutes item', () => {
let item;
const setItem = ({
show_buy_pipeline_minutes,
show_with_subtext,
show_notification_dot,
} = {}) => {
createWrapper({
pipeline_minutes: {
...userMenuMockPipelineMinutes,
show_buy_pipeline_minutes,
show_with_subtext,
show_notification_dot,
},
});
item = wrapper.findByTestId('buy-pipeline-minutes-item');
};
describe('When does NOT meet the condition to buy CI minutes', () => {
beforeEach(() => {
setItem();
});
it('does NOT render the buy pipeline minutes item', () => {
expect(item.exists()).toBe(false);
});
it('does not track the Sentry event', () => {
showDropdown();
expect(trackingSpy).not.toHaveBeenCalled();
});
});
describe('When does meet the condition to buy CI minutes', () => {
it('does render the menu item', () => {
setItem({ show_buy_pipeline_minutes: true });
expect(item.exists()).toBe(true);
});
it('tracks the Sentry event', () => {
setItem({ show_buy_pipeline_minutes: true });
showDropdown();
expect(trackingSpy).toHaveBeenCalledWith(
undefined,
userMenuMockPipelineMinutes.tracking_attrs['track-action'],
{
label: userMenuMockPipelineMinutes.tracking_attrs['track-label'],
property: userMenuMockPipelineMinutes.tracking_attrs['track-property'],
},
);
});
describe('Callout & notification dot', () => {
let spyFactory;
beforeEach(() => {
spyFactory = jest.spyOn(PersistentUserCallout, 'factory');
});
describe('When `show_notification_dot` is `false`', () => {
beforeEach(() => {
setItem({ show_buy_pipeline_minutes: true, show_notification_dot: false });
showDropdown();
});
it('does not set callout attributes', () => {
expect(item.attributes()).not.toEqual(
expect.objectContaining({
'data-feature-id': userMenuMockPipelineMinutes.callout_attrs.feature_id,
'data-dismiss-endpoint': userMenuMockPipelineMinutes.callout_attrs.dismiss_endpoint,
}),
);
});
it('does not initialize the Persistent Callout', () => {
expect(spyFactory).not.toHaveBeenCalled();
});
it('does not render notification dot', () => {
expect(wrapper.findByTestId('buy-pipeline-minutes-notification-dot').exists()).toBe(
false,
);
});
});
describe('When `show_notification_dot` is `true`', () => {
beforeEach(() => {
setItem({ show_buy_pipeline_minutes: true, show_notification_dot: true });
showDropdown();
});
it('sets the callout data attributes', () => {
expect(item.attributes()).toEqual(
expect.objectContaining({
'data-feature-id': userMenuMockPipelineMinutes.callout_attrs.feature_id,
'data-dismiss-endpoint': userMenuMockPipelineMinutes.callout_attrs.dismiss_endpoint,
}),
);
});
it('initializes the Persistent Callout', () => {
expect(spyFactory).toHaveBeenCalled();
});
it('renders notification dot', () => {
expect(wrapper.findByTestId('buy-pipeline-minutes-notification-dot').exists()).toBe(
true,
);
});
});
});
describe('Warning message', () => {
it('does not display the warning message when `show_with_subtext` is `false`', () => {
setItem({ show_buy_pipeline_minutes: true });
expect(item.text()).not.toContain(UserMenu.i18n.oneOfGroupsRunningOutOfPipelineMinutes);
});
it('displays the text and warning message when `show_with_subtext` is true', () => {
setItem({ show_buy_pipeline_minutes: true, show_with_subtext: true });
expect(item.text()).toContain(UserMenu.i18n.oneOfGroupsRunningOutOfPipelineMinutes);
});
});
});
});
describe('Edit profile item', () => {
it('should render a link to the profile page', () => {
createWrapper();
const item = wrapper.findByTestId('edit-profile-item');
expect(item.text()).toBe(UserMenu.i18n.editProfile);
expect(item.find('a').attributes('href')).toBe(userMenuMockData.settings.profile_path);
});
});
describe('Preferences item', () => {
it('should render a link to the profile page', () => {
createWrapper();
const item = wrapper.findByTestId('preferences-item');
expect(item.text()).toBe(UserMenu.i18n.preferences);
expect(item.find('a').attributes('href')).toBe(
userMenuMockData.settings.profile_preferences_path,
);
});
});
describe('GitLab Next item', () => {
describe('on gitlab.com', () => {
it('should render a link to switch to GitLab Next', () => {
createWrapper({ gitlab_com_but_not_canary: true });
const item = wrapper.findByTestId('gitlab-next-item');
expect(item.text()).toBe(UserMenu.i18n.gitlabNext);
expect(item.find('a').attributes('href')).toBe(userMenuMockData.canary_toggle_com_url);
});
});
describe('anywhere else', () => {
it('should not render the GitLab Next link', () => {
createWrapper({ gitlab_com_but_not_canary: false });
const item = wrapper.findByTestId('gitlab-next-item');
expect(item.exists()).toBe(false);
});
});
});
describe('New navigation toggle item', () => {
it('should render menu item with new navigation toggle', () => {
createWrapper();
const toggleItem = wrapper.findComponent(NewNavToggle);
expect(toggleItem.exists()).toBe(true);
expect(toggleItem.props('endpoint')).toBe(toggleNewNavEndpoint);
});
});
describe('Feedback item', () => {
it('should render feedback item with a link to a new GitLab issue', () => {
createWrapper();
const feedbackItem = wrapper.findByTestId('feedback-item');
expect(feedbackItem.find('a').attributes('href')).toBe(UserMenu.feedbackUrl);
});
});
describe('Sign out group', () => {
const findSignOutGroup = () => wrapper.findByTestId('sign-out-group');
it('should not render sign out group when user cannot sign out', () => {
createWrapper();
expect(findSignOutGroup().exists()).toBe(false);
});
describe('when user can sign out', () => {
beforeEach(() => {
createWrapper({ can_sign_out: true });
});
it('should render sign out group', () => {
expect(findSignOutGroup().exists()).toBe(true);
});
it('should render the menu item with a link to sign out and correct data attribute', () => {
expect(findSignOutGroup().find('a').attributes('href')).toBe(
userMenuMockData.sign_out_link,
);
expect(findSignOutGroup().find('a').attributes('data-method')).toBe('post');
});
});
});
});