import { GlBadge } from '@gitlab/ui';
import Vuex from 'vuex';
import Vue, { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { __ } from '~/locale';
import CreateMenu from '~/super_sidebar/components/create_menu.vue';
import SearchModal from '~/super_sidebar/components/global_search/components/global_search.vue';
import MergeRequestMenu from '~/super_sidebar/components/merge_request_menu.vue';
import Counter from '~/super_sidebar/components/counter.vue';
import UserBar from '~/super_sidebar/components/user_bar.vue';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
import { userCounts } from '~/super_sidebar/user_counts_manager';
import { sidebarData } from '../mock_data';
import { MOCK_DEFAULT_SEARCH_OPTIONS } from './global_search/mock_data';
describe('UserBar component', () => {
let wrapper;
const findCreateMenu = () => wrapper.findComponent(CreateMenu);
const findCounter = (at) => wrapper.findAllComponents(Counter).at(at);
const findIssuesCounter = () => findCounter(0);
const findMRsCounter = () => findCounter(1);
const findTodosCounter = () => findCounter(2);
const findMergeRequestMenu = () => wrapper.findComponent(MergeRequestMenu);
const findBrandLogo = () => wrapper.findByTestId('brand-header-custom-logo');
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);
const store = new Vuex.Store({
getters: {
searchOptions: () => MOCK_DEFAULT_SEARCH_OPTIONS,
},
});
const createWrapper = ({
hasCollapseButton = true,
extraSidebarData = {},
provideOverrides = {},
} = {}) => {
wrapper = shallowMountExtended(UserBar, {
propsData: {
hasCollapseButton,
sidebarData: { ...sidebarData, ...extraSidebarData },
},
provide: {
rootPath: '/',
toggleNewNavEndpoint: '/-/profile/preferences',
isImpersonating: false,
...provideOverrides,
},
directives: {
GlTooltip: createMockDirective('gl-tooltip'),
},
store,
});
};
describe('default', () => {
beforeEach(() => {
createWrapper();
});
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);
});
it('renders issues counter', () => {
const isuesCounter = findIssuesCounter();
expect(isuesCounter.props('count')).toBe(userCounts.assigned_issues);
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');
});
it('renders merge requests counter', () => {
const mrsCounter = findMRsCounter();
expect(mrsCounter.props('count')).toBe(
userCounts.assigned_merge_requests + userCounts.review_requested_merge_requests,
);
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');
});
describe('Todos counter', () => {
it('renders it', () => {
const todosCounter = findTodosCounter();
expect(todosCounter.props('href')).toBe(sidebarData.todos_dashboard_path);
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 update todo counter when event is emitted', async () => {
createWrapper();
const count = 100;
document.dispatchEvent(new CustomEvent('todo:toggle', { detail: { count } }));
await nextTick();
expect(findTodosCounter().props('count')).toBe(count);
});
});
it('renders branding logo', () => {
expect(findBrandLogo().exists()).toBe(true);
expect(findBrandLogo().attributes('src')).toBe(sidebarData.logo_url);
});
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);
});
});
describe('GitLab Next badge', () => {
describe('when on canary', () => {
it('should render a badge to switch off GitLab Next', () => {
createWrapper({ extraSidebarData: { gitlab_com_and_canary: true } });
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', () => {
createWrapper({ extraSidebarData: { gitlab_com_and_canary: false } });
const badge = wrapper.findComponent(GlBadge);
expect(badge.exists()).toBe(false);
});
});
});
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 /`);
});
it('should render search modal', () => {
expect(findSearchModal().exists()).toBe(true);
});
describe('Search tooltip', () => {
it('should hide search tooltip when modal is shown', async () => {
findSearchModal().vm.$emit('shown');
await nextTick();
const tooltip = getBinding(findSearchButton().element, 'gl-tooltip');
expect(tooltip.value).toBe('');
});
it('should add search tooltip when modal is hidden', async () => {
findSearchModal().vm.$emit('hidden');
await nextTick();
const tooltip = getBinding(findSearchButton().element, 'gl-tooltip');
expect(tooltip.value).toBe(`Search GitLab /`);
});
});
});
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');
});
});
});