diff options
Diffstat (limited to 'spec/frontend/super_sidebar/components/nav_item_spec.js')
-rw-r--r-- | spec/frontend/super_sidebar/components/nav_item_spec.js | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/spec/frontend/super_sidebar/components/nav_item_spec.js b/spec/frontend/super_sidebar/components/nav_item_spec.js new file mode 100644 index 00000000000..54ac4965ad8 --- /dev/null +++ b/spec/frontend/super_sidebar/components/nav_item_spec.js @@ -0,0 +1,156 @@ +import { GlBadge } from '@gitlab/ui'; +import { RouterLinkStub } from '@vue/test-utils'; +import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper'; +import NavItem from '~/super_sidebar/components/nav_item.vue'; +import NavItemRouterLink from '~/super_sidebar/components/nav_item_router_link.vue'; +import NavItemLink from '~/super_sidebar/components/nav_item_link.vue'; +import { + CLICK_MENU_ITEM_ACTION, + TRACKING_UNKNOWN_ID, + TRACKING_UNKNOWN_PANEL, +} from '~/super_sidebar/constants'; + +describe('NavItem component', () => { + let wrapper; + + const findLink = () => wrapper.findByTestId('nav-item-link'); + const findPill = () => wrapper.findComponent(GlBadge); + const findNavItemRouterLink = () => extendedWrapper(wrapper.findComponent(NavItemRouterLink)); + const findNavItemLink = () => extendedWrapper(wrapper.findComponent(NavItemLink)); + + const createWrapper = ({ item, props = {}, provide = {}, routerLinkSlotProps = {} }) => { + wrapper = mountExtended(NavItem, { + propsData: { + item, + ...props, + }, + provide, + stubs: { + RouterLink: { + ...RouterLinkStub, + render() { + const children = this.$scopedSlots.default({ + href: '/foo', + isActive: false, + navigate: jest.fn(), + ...routerLinkSlotProps, + }); + return children; + }, + }, + }, + }); + }; + + describe('pills', () => { + it.each([0, 5, 3.4, 'foo', '10%'])('item with pill_data `%p` renders a pill', (pillCount) => { + createWrapper({ item: { title: 'Foo', pill_count: pillCount } }); + + expect(findPill().text()).toEqual(pillCount.toString()); + }); + + it.each([null, undefined, false, true, '', NaN, Number.POSITIVE_INFINITY])( + 'item with pill_data `%p` renders no pill', + (pillCount) => { + createWrapper({ item: { title: 'Foo', pill_count: pillCount } }); + + expect(findPill().exists()).toEqual(false); + }, + ); + }); + + it('applies custom link classes', () => { + const customClass = 'customClass'; + createWrapper({ + item: { title: 'Foo' }, + props: { + linkClasses: { + [customClass]: true, + }, + }, + }); + + expect(findLink().attributes('class')).toContain(customClass); + }); + + it('applies custom classes set in the backend', () => { + const customClass = 'customBackendClass'; + createWrapper({ item: { title: 'Foo', link_classes: customClass } }); + + expect(findLink().attributes('class')).toContain(customClass); + }); + + it('applies data-method specified in the backend', () => { + const method = 'post'; + createWrapper({ item: { title: 'Foo', data_method: method } }); + + expect(findLink().attributes('data-method')).toContain(method); + }); + + describe('Data Tracking Attributes', () => { + it.each` + id | panelType | eventLabel | eventProperty | eventExtra + ${'abc'} | ${'xyz'} | ${'abc'} | ${'nav_panel_xyz'} | ${undefined} + ${undefined} | ${'xyz'} | ${TRACKING_UNKNOWN_ID} | ${'nav_panel_xyz'} | ${'{"title":"Foo"}'} + ${'abc'} | ${undefined} | ${'abc'} | ${TRACKING_UNKNOWN_PANEL} | ${'{"title":"Foo"}'} + ${undefined} | ${undefined} | ${TRACKING_UNKNOWN_ID} | ${TRACKING_UNKNOWN_PANEL} | ${'{"title":"Foo"}'} + `( + 'adds appropriate data tracking labels for id=$id and panelType=$panelType', + ({ id, eventLabel, panelType, eventProperty, eventExtra }) => { + createWrapper({ item: { title: 'Foo', id }, props: {}, provide: { panelType } }); + + expect(findLink().attributes('data-track-action')).toBe(CLICK_MENU_ITEM_ACTION); + expect(findLink().attributes('data-track-label')).toBe(eventLabel); + expect(findLink().attributes('data-track-property')).toBe(eventProperty); + expect(findLink().attributes('data-track-extra')).toBe(eventExtra); + }, + ); + }); + + describe('when `item` prop has `to` attribute', () => { + describe('when `RouterLink` is not active', () => { + it('renders `NavItemRouterLink` with active indicator hidden', () => { + createWrapper({ item: { title: 'Foo', to: { name: 'foo' } } }); + + expect(findNavItemRouterLink().findByTestId('active-indicator').classes()).toContain( + 'gl-bg-transparent', + ); + }); + }); + + describe('when `RouterLink` is active', () => { + it('renders `NavItemRouterLink` with active indicator shown', () => { + createWrapper({ + item: { title: 'Foo', to: { name: 'foo' } }, + routerLinkSlotProps: { isActive: true }, + }); + + expect(findNavItemRouterLink().findByTestId('active-indicator').classes()).toContain( + 'gl-bg-blue-500', + ); + }); + }); + }); + + describe('when `item` prop has `link` attribute', () => { + describe('when `item` has `is_active` set to `false`', () => { + it('renders `NavItemLink` with active indicator hidden', () => { + createWrapper({ item: { title: 'Foo', link: '/foo', is_active: false } }); + + expect(findNavItemLink().findByTestId('active-indicator').classes()).toContain( + 'gl-bg-transparent', + ); + }); + }); + + describe('when `item` has `is_active` set to `true`', () => { + it('renders `NavItemLink` with active indicator shown', () => { + createWrapper({ item: { title: 'Foo', link: '/foo', is_active: true } }); + + expect(findNavItemLink().findByTestId('active-indicator').classes()).toContain( + 'gl-bg-blue-500', + ); + }); + }); + }); +}); |