2023-05-27 22:25:52 +05:30
|
|
|
import { GlBadge } from '@gitlab/ui';
|
2023-06-20 00:43:36 +05:30
|
|
|
import Vuex from 'vuex';
|
|
|
|
import Vue, { nextTick } from 'vue';
|
2023-03-17 16:20:25 +05:30
|
|
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
|
|
|
import { __ } from '~/locale';
|
2023-04-23 21:23:45 +05:30
|
|
|
import CreateMenu from '~/super_sidebar/components/create_menu.vue';
|
2023-06-20 00:43:36 +05:30
|
|
|
import SearchModal from '~/super_sidebar/components/global_search/components/global_search.vue';
|
2023-04-23 21:23:45 +05:30
|
|
|
import MergeRequestMenu from '~/super_sidebar/components/merge_request_menu.vue';
|
2023-03-17 16:20:25 +05:30
|
|
|
import Counter from '~/super_sidebar/components/counter.vue';
|
|
|
|
import UserBar from '~/super_sidebar/components/user_bar.vue';
|
2023-06-20 00:43:36 +05:30
|
|
|
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
|
|
|
import waitForPromises from 'helpers/wait_for_promises';
|
|
|
|
import { highCountTrim } from '~/lib/utils/text_utility';
|
2023-03-17 16:20:25 +05:30
|
|
|
import { sidebarData } from '../mock_data';
|
2023-06-20 00:43:36 +05:30
|
|
|
import { MOCK_DEFAULT_SEARCH_OPTIONS } from './global_search/mock_data';
|
|
|
|
|
|
|
|
jest.mock('~/lib/utils/text_utility', () => ({
|
|
|
|
highCountTrim: jest.fn().mockReturnValue('99+'),
|
|
|
|
}));
|
2023-03-17 16:20:25 +05:30
|
|
|
|
|
|
|
describe('UserBar component', () => {
|
|
|
|
let wrapper;
|
|
|
|
|
2023-04-23 21:23:45 +05:30
|
|
|
const findCreateMenu = () => wrapper.findComponent(CreateMenu);
|
2023-03-17 16:20:25 +05:30
|
|
|
const findCounter = (at) => wrapper.findAllComponents(Counter).at(at);
|
2023-06-20 00:43:36 +05:30
|
|
|
const findIssuesCounter = () => findCounter(0);
|
|
|
|
const findMRsCounter = () => findCounter(1);
|
|
|
|
const findTodosCounter = () => findCounter(2);
|
2023-04-23 21:23:45 +05:30
|
|
|
const findMergeRequestMenu = () => wrapper.findComponent(MergeRequestMenu);
|
2023-05-27 22:25:52 +05:30
|
|
|
const findBrandLogo = () => wrapper.findByTestId('brand-header-custom-logo');
|
2023-06-20 00:43:36 +05:30
|
|
|
const findCollapseButton = () => wrapper.findByTestId('super-sidebar-collapse-button');
|
|
|
|
const findSearchButton = () => wrapper.findByTestId('super-sidebar-search-button');
|
|
|
|
const findSearchModal = () => wrapper.findComponent(SearchModal);
|
|
|
|
const findStopImpersonationButton = () => wrapper.findByTestId('stop-impersonation-btn');
|
|
|
|
|
|
|
|
Vue.use(Vuex);
|
2023-03-17 16:20:25 +05:30
|
|
|
|
2023-06-20 00:43:36 +05:30
|
|
|
const store = new Vuex.Store({
|
|
|
|
getters: {
|
|
|
|
searchOptions: () => MOCK_DEFAULT_SEARCH_OPTIONS,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const createWrapper = ({
|
|
|
|
hasCollapseButton = true,
|
|
|
|
extraSidebarData = {},
|
|
|
|
provideOverrides = {},
|
|
|
|
} = {}) => {
|
2023-03-17 16:20:25 +05:30
|
|
|
wrapper = shallowMountExtended(UserBar, {
|
|
|
|
propsData: {
|
2023-06-20 00:43:36 +05:30
|
|
|
hasCollapseButton,
|
2023-05-27 22:25:52 +05:30
|
|
|
sidebarData: { ...sidebarData, ...extraSidebarData },
|
2023-03-17 16:20:25 +05:30
|
|
|
},
|
|
|
|
provide: {
|
|
|
|
rootPath: '/',
|
|
|
|
toggleNewNavEndpoint: '/-/profile/preferences',
|
2023-06-20 00:43:36 +05:30
|
|
|
isImpersonating: false,
|
|
|
|
...provideOverrides,
|
2023-03-17 16:20:25 +05:30
|
|
|
},
|
2023-06-20 00:43:36 +05:30
|
|
|
directives: {
|
|
|
|
GlTooltip: createMockDirective('gl-tooltip'),
|
|
|
|
},
|
|
|
|
store,
|
2023-03-17 16:20:25 +05:30
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('default', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createWrapper();
|
|
|
|
});
|
|
|
|
|
2023-04-23 21:23:45 +05:30
|
|
|
it('passes the "Create new..." menu groups to the create-menu component', () => {
|
|
|
|
expect(findCreateMenu().props('groups')).toBe(sidebarData.create_new_menu_groups);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('passes the "Merge request" menu groups to the merge_request_menu component', () => {
|
|
|
|
expect(findMergeRequestMenu().props('items')).toBe(sidebarData.merge_request_menu);
|
|
|
|
});
|
|
|
|
|
2023-03-17 16:20:25 +05:30
|
|
|
it('renders issues counter', () => {
|
2023-06-20 00:43:36 +05:30
|
|
|
const isuesCounter = findIssuesCounter();
|
|
|
|
expect(isuesCounter.props('count')).toBe(sidebarData.assigned_open_issues_count);
|
|
|
|
expect(isuesCounter.props('href')).toBe(sidebarData.issues_dashboard_path);
|
|
|
|
expect(isuesCounter.props('label')).toBe(__('Issues'));
|
|
|
|
expect(isuesCounter.attributes('data-track-action')).toBe('click_link');
|
|
|
|
expect(isuesCounter.attributes('data-track-label')).toBe('issues_link');
|
|
|
|
expect(isuesCounter.attributes('data-track-property')).toBe('nav_core_menu');
|
|
|
|
expect(isuesCounter.attributes('class')).toContain('dashboard-shortcuts-issues');
|
2023-03-17 16:20:25 +05:30
|
|
|
});
|
|
|
|
|
2023-04-23 21:23:45 +05:30
|
|
|
it('renders merge requests counter', () => {
|
2023-06-20 00:43:36 +05:30
|
|
|
const mrsCounter = findMRsCounter();
|
|
|
|
expect(mrsCounter.props('count')).toBe(sidebarData.total_merge_requests_count);
|
|
|
|
expect(mrsCounter.props('label')).toBe(__('Merge requests'));
|
|
|
|
expect(mrsCounter.attributes('data-track-action')).toBe('click_dropdown');
|
|
|
|
expect(mrsCounter.attributes('data-track-label')).toBe('merge_requests_menu');
|
|
|
|
expect(mrsCounter.attributes('data-track-property')).toBe('nav_core_menu');
|
2023-04-23 21:23:45 +05:30
|
|
|
});
|
|
|
|
|
2023-06-20 00:43:36 +05:30
|
|
|
describe('Todos counter', () => {
|
|
|
|
it('renders it', () => {
|
|
|
|
const todosCounter = findTodosCounter();
|
|
|
|
expect(todosCounter.props('href')).toBe('/dashboard/todos');
|
|
|
|
expect(todosCounter.props('label')).toBe(__('To-Do list'));
|
|
|
|
expect(todosCounter.attributes('data-track-action')).toBe('click_link');
|
|
|
|
expect(todosCounter.attributes('data-track-label')).toBe('todos_link');
|
|
|
|
expect(todosCounter.attributes('data-track-property')).toBe('nav_core_menu');
|
|
|
|
expect(todosCounter.attributes('class')).toContain('shortcuts-todos');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should format and update todo counter when event is emitted', async () => {
|
|
|
|
createWrapper();
|
|
|
|
const count = 100;
|
|
|
|
document.dispatchEvent(new CustomEvent('todo:toggle', { detail: { count } }));
|
|
|
|
await nextTick();
|
|
|
|
expect(highCountTrim).toHaveBeenCalledWith(count);
|
|
|
|
expect(findTodosCounter().props('count')).toBe('99+');
|
|
|
|
});
|
2023-03-17 16:20:25 +05:30
|
|
|
});
|
2023-05-27 22:25:52 +05:30
|
|
|
|
|
|
|
it('renders branding logo', () => {
|
|
|
|
expect(findBrandLogo().exists()).toBe(true);
|
|
|
|
expect(findBrandLogo().attributes('src')).toBe(sidebarData.logo_url);
|
|
|
|
});
|
2023-06-20 00:43:36 +05:30
|
|
|
|
|
|
|
it('does not render the "Stop impersonating" button', () => {
|
|
|
|
expect(findStopImpersonationButton().exists()).toBe(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders collapse button when hasCollapseButton is true', () => {
|
|
|
|
expect(findCollapseButton().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('does not render collapse button when hasCollapseButton is false', () => {
|
|
|
|
createWrapper({ hasCollapseButton: false });
|
|
|
|
expect(findCollapseButton().exists()).toBe(false);
|
|
|
|
});
|
2023-05-27 22:25:52 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
describe('GitLab Next badge', () => {
|
|
|
|
describe('when on canary', () => {
|
|
|
|
it('should render a badge to switch off GitLab Next', () => {
|
2023-06-20 00:43:36 +05:30
|
|
|
createWrapper({ extraSidebarData: { gitlab_com_and_canary: true } });
|
2023-05-27 22:25:52 +05:30
|
|
|
const badge = wrapper.findComponent(GlBadge);
|
|
|
|
expect(badge.text()).toBe('Next');
|
|
|
|
expect(badge.attributes('href')).toBe(sidebarData.canary_toggle_com_url);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('when not on canary', () => {
|
|
|
|
it('should not render the GitLab Next badge', () => {
|
2023-06-20 00:43:36 +05:30
|
|
|
createWrapper({ extraSidebarData: { gitlab_com_and_canary: false } });
|
2023-05-27 22:25:52 +05:30
|
|
|
const badge = wrapper.findComponent(GlBadge);
|
|
|
|
expect(badge.exists()).toBe(false);
|
|
|
|
});
|
|
|
|
});
|
2023-03-17 16:20:25 +05:30
|
|
|
});
|
2023-06-20 00:43:36 +05:30
|
|
|
|
|
|
|
describe('Search', () => {
|
|
|
|
beforeEach(async () => {
|
|
|
|
createWrapper();
|
|
|
|
await waitForPromises();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render search button', () => {
|
|
|
|
expect(findSearchButton().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('search button should have tooltip', () => {
|
|
|
|
const tooltip = getBinding(findSearchButton().element, 'gl-tooltip');
|
|
|
|
expect(tooltip.value).toBe(`Search GitLab <kbd>/</kbd>`);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should render search modal', () => {
|
|
|
|
expect(findSearchModal().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
describe('While impersonating a user', () => {
|
|
|
|
beforeEach(() => {
|
|
|
|
createWrapper({ provideOverrides: { isImpersonating: true } });
|
|
|
|
});
|
|
|
|
|
|
|
|
it('renders the "Stop impersonating" button', () => {
|
|
|
|
expect(findStopImpersonationButton().exists()).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets the correct label on the button', () => {
|
|
|
|
const btn = findStopImpersonationButton();
|
|
|
|
const label = __('Stop impersonating');
|
|
|
|
|
|
|
|
expect(btn.attributes('title')).toBe(label);
|
|
|
|
expect(btn.attributes('aria-label')).toBe(label);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('sets the href and data-method attributes', () => {
|
|
|
|
const btn = findStopImpersonationButton();
|
|
|
|
|
|
|
|
expect(btn.attributes('href')).toBe(sidebarData.stop_impersonation_path);
|
|
|
|
expect(btn.attributes('data-method')).toBe('delete');
|
|
|
|
});
|
|
|
|
});
|
2023-03-17 16:20:25 +05:30
|
|
|
});
|