debian-mirror-gitlab/spec/frontend/super_sidebar/components/super_sidebar_spec.js
2023-06-20 00:43:36 +05:30

188 lines
6.3 KiB
JavaScript

import { nextTick } from 'vue';
import { GlCollapse } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import SuperSidebar from '~/super_sidebar/components/super_sidebar.vue';
import HelpCenter from '~/super_sidebar/components/help_center.vue';
import UserBar from '~/super_sidebar/components/user_bar.vue';
import SidebarPortalTarget from '~/super_sidebar/components/sidebar_portal_target.vue';
import ContextSwitcher from '~/super_sidebar/components/context_switcher.vue';
import {
SUPER_SIDEBAR_PEEK_OPEN_DELAY,
SUPER_SIDEBAR_PEEK_CLOSE_DELAY,
} from '~/super_sidebar/constants';
import { stubComponent } from 'helpers/stub_component';
import { sidebarData } from '../mock_data';
const focusInputMock = jest.fn();
describe('SuperSidebar component', () => {
let wrapper;
const findSidebar = () => wrapper.findByTestId('super-sidebar');
const findHoverArea = () => wrapper.findByTestId('super-sidebar-hover-area');
const findUserBar = () => wrapper.findComponent(UserBar);
const findHelpCenter = () => wrapper.findComponent(HelpCenter);
const findSidebarPortalTarget = () => wrapper.findComponent(SidebarPortalTarget);
const createWrapper = ({ props = {}, provide = {}, sidebarState = {} } = {}) => {
wrapper = shallowMountExtended(SuperSidebar, {
data() {
return {
...sidebarState,
};
},
propsData: {
sidebarData,
...props,
},
stubs: {
ContextSwitcher: stubComponent(ContextSwitcher, {
methods: { focusInput: focusInputMock },
}),
},
provide,
});
};
describe('default', () => {
it('adds inert attribute when collapsed', () => {
createWrapper({ sidebarState: { isCollapsed: true } });
expect(findSidebar().attributes('inert')).toBe('inert');
});
it('does not add inert attribute when expanded', () => {
createWrapper();
expect(findSidebar().attributes('inert')).toBe(undefined);
});
it('renders UserBar with sidebarData', () => {
createWrapper();
expect(findUserBar().props('sidebarData')).toBe(sidebarData);
});
it('renders HelpCenter with sidebarData', () => {
createWrapper();
expect(findHelpCenter().props('sidebarData')).toBe(sidebarData);
});
it('renders SidebarPortalTarget', () => {
createWrapper();
expect(findSidebarPortalTarget().exists()).toBe(true);
});
it("does not call the context switcher's focusInput method initially", () => {
createWrapper();
expect(focusInputMock).not.toHaveBeenCalled();
});
it('renders hidden shortcut links', () => {
createWrapper();
const [linkAttrs] = sidebarData.shortcut_links;
const link = wrapper.find(`.${linkAttrs.css_class}`);
expect(link.exists()).toBe(true);
expect(link.attributes('href')).toBe(linkAttrs.href);
expect(link.attributes('class')).toContain('gl-display-none');
});
});
describe('when peeking on hover', () => {
const peekClass = 'super-sidebar-peek';
it('updates inert attribute and peek class', async () => {
createWrapper({
provide: { glFeatures: { superSidebarPeek: true } },
sidebarState: { isCollapsed: true },
});
findHoverArea().trigger('mouseenter');
jest.advanceTimersByTime(SUPER_SIDEBAR_PEEK_OPEN_DELAY - 1);
await nextTick();
// Not quite enough time has elapsed yet for sidebar to open
expect(findSidebar().classes()).not.toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe('inert');
jest.advanceTimersByTime(1);
await nextTick();
// Exactly enough time has elapsed to open
expect(findSidebar().classes()).toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe(undefined);
// Important: assume the cursor enters the sidebar
findSidebar().trigger('mouseenter');
jest.runAllTimers();
await nextTick();
// Sidebar remains peeked open indefinitely without a mouseleave
expect(findSidebar().classes()).toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe(undefined);
findSidebar().trigger('mouseleave');
jest.advanceTimersByTime(SUPER_SIDEBAR_PEEK_CLOSE_DELAY - 1);
await nextTick();
// Not quite enough time has elapsed yet for sidebar to hide
expect(findSidebar().classes()).toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe(undefined);
jest.advanceTimersByTime(1);
await nextTick();
// Exactly enough time has elapsed for sidebar to hide
expect(findSidebar().classes()).not.toContain('super-sidebar-peek');
expect(findSidebar().attributes('inert')).toBe('inert');
});
it('eventually closes the sidebar if cursor never enters sidebar', async () => {
createWrapper({
provide: { glFeatures: { superSidebarPeek: true } },
sidebarState: { isCollapsed: true },
});
findHoverArea().trigger('mouseenter');
jest.advanceTimersByTime(SUPER_SIDEBAR_PEEK_OPEN_DELAY);
await nextTick();
// Sidebar is now open
expect(findSidebar().classes()).toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe(undefined);
// Important: do *not* fire a mouseenter event on the sidebar here. This
// imitates what happens if the cursor moves away from the sidebar before
// it actually appears.
jest.advanceTimersByTime(SUPER_SIDEBAR_PEEK_CLOSE_DELAY - 1);
await nextTick();
// Not quite enough time has elapsed yet for sidebar to hide
expect(findSidebar().classes()).toContain(peekClass);
expect(findSidebar().attributes('inert')).toBe(undefined);
jest.advanceTimersByTime(1);
await nextTick();
// Exactly enough time has elapsed for sidebar to hide
expect(findSidebar().classes()).not.toContain('super-sidebar-peek');
expect(findSidebar().attributes('inert')).toBe('inert');
});
});
describe('when opening the context switcher', () => {
beforeEach(() => {
createWrapper();
wrapper.findComponent(GlCollapse).vm.$emit('input', true);
wrapper.findComponent(GlCollapse).vm.$emit('shown');
});
it("calls the context switcher's focusInput method", () => {
expect(focusInputMock).toHaveBeenCalledTimes(1);
});
});
});