summaryrefslogtreecommitdiff
path: root/spec/frontend/super_sidebar
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/super_sidebar')
-rw-r--r--spec/frontend/super_sidebar/components/nav_item_link_spec.js37
-rw-r--r--spec/frontend/super_sidebar/components/nav_item_router_link_spec.js56
-rw-r--r--spec/frontend/super_sidebar/components/nav_item_spec.js89
-rw-r--r--spec/frontend/super_sidebar/utils_spec.js11
4 files changed, 182 insertions, 11 deletions
diff --git a/spec/frontend/super_sidebar/components/nav_item_link_spec.js b/spec/frontend/super_sidebar/components/nav_item_link_spec.js
new file mode 100644
index 00000000000..5cc1bd01d0f
--- /dev/null
+++ b/spec/frontend/super_sidebar/components/nav_item_link_spec.js
@@ -0,0 +1,37 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import NavItemLink from '~/super_sidebar/components/nav_item_link.vue';
+
+describe('NavItemLink component', () => {
+ let wrapper;
+
+ const createWrapper = (item) => {
+ wrapper = shallowMountExtended(NavItemLink, {
+ propsData: {
+ item,
+ },
+ });
+ };
+
+ describe('when `item` has `is_active` set to `false`', () => {
+ it('renders an anchor tag without active CSS class and `aria-current` attribute', () => {
+ createWrapper({ title: 'foo', link: '/foo', is_active: false });
+
+ expect(wrapper.attributes()).toEqual({
+ href: '/foo',
+ class: '',
+ });
+ });
+ });
+
+ describe('when `item` has `is_active` set to `true`', () => {
+ it('renders an anchor tag with active CSS class and `aria-current="page"`', () => {
+ createWrapper({ title: 'foo', link: '/foo', is_active: true });
+
+ expect(wrapper.attributes()).toEqual({
+ href: '/foo',
+ class: 'gl-bg-t-gray-a-08',
+ 'aria-current': 'page',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/super_sidebar/components/nav_item_router_link_spec.js b/spec/frontend/super_sidebar/components/nav_item_router_link_spec.js
new file mode 100644
index 00000000000..a7ca56325fe
--- /dev/null
+++ b/spec/frontend/super_sidebar/components/nav_item_router_link_spec.js
@@ -0,0 +1,56 @@
+import { RouterLinkStub } from '@vue/test-utils';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import NavItemRouterLink from '~/super_sidebar/components/nav_item_router_link.vue';
+
+describe('NavItemRouterLink component', () => {
+ let wrapper;
+
+ const createWrapper = ({ item, routerLinkSlotProps = {} }) => {
+ wrapper = mountExtended(NavItemRouterLink, {
+ propsData: {
+ item,
+ },
+ stubs: {
+ RouterLink: {
+ ...RouterLinkStub,
+ render() {
+ const children = this.$scopedSlots.default({
+ href: '/foo',
+ isActive: false,
+ navigate: jest.fn(),
+ ...routerLinkSlotProps,
+ });
+ return children;
+ },
+ },
+ },
+ });
+ };
+
+ describe('when `RouterLink` is not active', () => {
+ it('renders an anchor tag without active CSS class and `aria-current` attribute', () => {
+ createWrapper({ item: { title: 'foo', to: { name: 'foo' } } });
+
+ expect(wrapper.attributes()).toEqual({
+ href: '/foo',
+ custom: '',
+ });
+ });
+ });
+
+ describe('when `RouterLink` is active', () => {
+ it('renders an anchor tag with active CSS class and `aria-current="page"`', () => {
+ createWrapper({
+ item: { title: 'foo', to: { name: 'foo' } },
+ routerLinkSlotProps: { isActive: true },
+ });
+
+ expect(wrapper.findComponent(RouterLinkStub).props('activeClass')).toBe('gl-bg-t-gray-a-08');
+ expect(wrapper.attributes()).toEqual({
+ href: '/foo',
+ 'aria-current': 'page',
+ custom: '',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/super_sidebar/components/nav_item_spec.js b/spec/frontend/super_sidebar/components/nav_item_spec.js
index 1714a4c3a4e..43b3f14f2f5 100644
--- a/spec/frontend/super_sidebar/components/nav_item_spec.js
+++ b/spec/frontend/super_sidebar/components/nav_item_spec.js
@@ -1,6 +1,9 @@
import { GlBadge } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+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,
@@ -12,19 +15,36 @@ describe('NavItem component', () => {
const findLink = () => wrapper.findByTestId('nav-item-link');
const findPill = () => wrapper.findComponent(GlBadge);
- const createWrapper = (item, props = {}, provide = {}) => {
- wrapper = shallowMountExtended(NavItem, {
+ 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({ title: 'Foo', pill_count: pillCount });
+ createWrapper({ item: { title: 'Foo', pill_count: pillCount } });
expect(findPill().text()).toEqual(pillCount.toString());
});
@@ -32,7 +52,7 @@ describe('NavItem component', () => {
it.each([null, undefined, false, true, '', NaN, Number.POSITIVE_INFINITY])(
'item with pill_data `%p` renders no pill',
(pillCount) => {
- createWrapper({ title: 'Foo', pill_count: pillCount });
+ createWrapper({ item: { title: 'Foo', pill_count: pillCount } });
expect(findPill().exists()).toEqual(false);
},
@@ -41,21 +61,21 @@ describe('NavItem component', () => {
it('applies custom link classes', () => {
const customClass = 'customClass';
- createWrapper(
- { title: 'Foo' },
- {
+ 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({ title: 'Foo', link_classes: customClass });
+ createWrapper({ item: { title: 'Foo', link_classes: customClass } });
expect(findLink().attributes('class')).toContain(customClass);
});
@@ -70,7 +90,7 @@ describe('NavItem component', () => {
`(
'adds appropriate data tracking labels for id=$id and panelType=$panelType',
({ id, eventLabel, panelType, eventProperty, eventExtra }) => {
- createWrapper({ title: 'Foo', id }, {}, { panelType });
+ 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);
@@ -79,4 +99,51 @@ describe('NavItem component', () => {
},
);
});
+
+ 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',
+ );
+ });
+ });
+ });
});
diff --git a/spec/frontend/super_sidebar/utils_spec.js b/spec/frontend/super_sidebar/utils_spec.js
index d2984254dee..8c8673ddbc4 100644
--- a/spec/frontend/super_sidebar/utils_spec.js
+++ b/spec/frontend/super_sidebar/utils_spec.js
@@ -2,6 +2,7 @@ import {
getTopFrequentItems,
trackContextAccess,
formatContextSwitcherItems,
+ ariaCurrent,
} from '~/super_sidebar/utils';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import AccessorUtilities from '~/lib/utils/accessor';
@@ -157,4 +158,14 @@ describe('Super sidebar utils spec', () => {
]);
});
});
+
+ describe('ariaCurrent', () => {
+ it.each`
+ isActive | expected
+ ${true} | ${'page'}
+ ${false} | ${null}
+ `('returns `$expected` when `isActive` is `$isActive`', ({ isActive, expected }) => {
+ expect(ariaCurrent(isActive)).toBe(expected);
+ });
+ });
});