diff options
Diffstat (limited to 'spec/frontend/nav')
9 files changed, 188 insertions, 95 deletions
diff --git a/spec/frontend/nav/components/new_nav_toggle_spec.js b/spec/frontend/nav/components/new_nav_toggle_spec.js index bad24345f9d..cf8e59d6522 100644 --- a/spec/frontend/nav/components/new_nav_toggle_spec.js +++ b/spec/frontend/nav/components/new_nav_toggle_spec.js @@ -1,16 +1,17 @@ import { mount, createWrapper } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import { getByText as getByTextHelper } from '@testing-library/dom'; -import { GlToggle } from '@gitlab/ui'; +import { GlDisclosureDropdownItem, GlToggle } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status'; import { useMockLocationHelper } from 'helpers/mock_window_location_helper'; import NewNavToggle from '~/nav/components/new_nav_toggle.vue'; import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/flash'; +import { createAlert } from '~/alert'; import { s__ } from '~/locale'; +import { mockTracking } from 'helpers/tracking_helper'; -jest.mock('~/flash'); +jest.mock('~/alert'); const TEST_ENDPONT = 'https://example.com/toggle'; @@ -18,8 +19,10 @@ describe('NewNavToggle', () => { useMockLocationHelper(); let wrapper; + let trackingSpy; const findToggle = () => wrapper.findComponent(GlToggle); + const findDisclosureItem = () => wrapper.findComponent(GlDisclosureDropdownItem); const createComponent = (propsData = { enabled: false }) => { wrapper = mount(NewNavToggle, { @@ -28,85 +31,184 @@ describe('NewNavToggle', () => { ...propsData, }, }); - }; - afterEach(() => { - wrapper.destroy(); - }); + trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn); + }; const getByText = (text, options) => createWrapper(getByTextHelper(wrapper.element, text, options)); - it('renders its title', () => { - createComponent(); - expect(getByText('Navigation redesign').exists()).toBe(true); - }); - - describe('when user preference is enabled', () => { - beforeEach(() => { - createComponent({ enabled: true }); - }); - - it('renders the toggle as enabled', () => { - expect(findToggle().props('value')).toBe(true); + describe('When rendered in scope of the new navigation', () => { + it('renders the disclosure item', () => { + createComponent({ newNavigation: true, enabled: true }); + expect(findDisclosureItem().exists()).toBe(true); }); - }); - describe('when user preference is disabled', () => { - beforeEach(() => { - createComponent({ enabled: false }); - }); + describe('when user preference is enabled', () => { + beforeEach(() => { + createComponent({ newNavigation: true, enabled: true }); + }); - it('renders the toggle as disabled', () => { - expect(findToggle().props('value')).toBe(false); + it('renders the toggle as enabled', () => { + expect(findToggle().props('value')).toBe(true); + }); }); - }); - describe.each` - desc | actFn - ${'when toggle button is clicked'} | ${() => findToggle().trigger('click')} - ${'when menu item text is clicked'} | ${() => getByText('New navigation').trigger('click')} - `('$desc', ({ actFn }) => { - let mock; + describe('when user preference is disabled', () => { + beforeEach(() => { + createComponent({ enabled: false }); + }); - beforeEach(() => { - mock = new MockAdapter(axios); - createComponent({ enabled: false }); + it('renders the toggle as disabled', () => { + expect(findToggle().props('value')).toBe(false); + }); }); - it('reloads the page on success', async () => { - mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK); - - actFn(); - await waitForPromises(); - - expect(window.location.reload).toHaveBeenCalled(); + describe.each` + desc | actFn | toggleValue | trackingLabel | trackingProperty + ${'when toggle button is clicked'} | ${() => findToggle().trigger('click')} | ${false} | ${'enable_new_nav_beta'} | ${'navigation_top'} + ${'when menu item text is clicked'} | ${() => getByText('New navigation').trigger('click')} | ${false} | ${'enable_new_nav_beta'} | ${'navigation_top'} + ${'when toggle button is clicked'} | ${() => findToggle().trigger('click')} | ${true} | ${'disable_new_nav_beta'} | ${'nav_user_menu'} + ${'when menu item text is clicked'} | ${() => getByText('New navigation').trigger('click')} | ${true} | ${'disable_new_nav_beta'} | ${'nav_user_menu'} + `('$desc', ({ actFn, toggleValue, trackingLabel, trackingProperty }) => { + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + createComponent({ enabled: toggleValue }); + }); + + it('reloads the page on success', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK); + + actFn(); + await waitForPromises(); + + expect(window.location.reload).toHaveBeenCalled(); + }); + + it('shows an alert on error', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + + actFn(); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith( + expect.objectContaining({ + message: s__( + 'NorthstarNavigation|Could not update the new navigation preference. Please try again later.', + ), + }), + ); + expect(window.location.reload).not.toHaveBeenCalled(); + }); + + it('changes the toggle', async () => { + await actFn(); + + expect(findToggle().props('value')).toBe(!toggleValue); + }); + + it('tracks the Snowplow event', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK); + await actFn(); + await waitForPromises(); + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_toggle', { + label: trackingLabel, + property: trackingProperty, + }); + }); + + afterEach(() => { + mock.restore(); + }); }); + }); - it('shows an alert on error', async () => { - mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + describe('When rendered in scope of the current navigation', () => { + it('renders its title', () => { + createComponent(); + expect(getByText('Navigation redesign').exists()).toBe(true); + }); - actFn(); - await waitForPromises(); + describe('when user preference is enabled', () => { + beforeEach(() => { + createComponent({ enabled: true }); + }); - expect(createAlert).toHaveBeenCalledWith( - expect.objectContaining({ - message: s__( - 'NorthstarNavigation|Could not update the new navigation preference. Please try again later.', - ), - }), - ); - expect(window.location.reload).not.toHaveBeenCalled(); + it('renders the toggle as enabled', () => { + expect(findToggle().props('value')).toBe(true); + }); }); - it('changes the toggle', async () => { - await actFn(); + describe('when user preference is disabled', () => { + beforeEach(() => { + createComponent({ enabled: false }); + }); - expect(findToggle().props('value')).toBe(true); + it('renders the toggle as disabled', () => { + expect(findToggle().props('value')).toBe(false); + }); }); - afterEach(() => { - mock.restore(); + describe.each` + desc | actFn | toggleValue | trackingLabel | trackingProperty + ${'when toggle button is clicked'} | ${() => findToggle().trigger('click')} | ${false} | ${'enable_new_nav_beta'} | ${'navigation_top'} + ${'when menu item text is clicked'} | ${() => getByText('New navigation').trigger('click')} | ${false} | ${'enable_new_nav_beta'} | ${'navigation_top'} + ${'when toggle button is clicked'} | ${() => findToggle().trigger('click')} | ${true} | ${'disable_new_nav_beta'} | ${'nav_user_menu'} + ${'when menu item text is clicked'} | ${() => getByText('New navigation').trigger('click')} | ${true} | ${'disable_new_nav_beta'} | ${'nav_user_menu'} + `('$desc', ({ actFn, toggleValue, trackingLabel, trackingProperty }) => { + let mock; + + beforeEach(() => { + mock = new MockAdapter(axios); + createComponent({ enabled: toggleValue }); + }); + + it('reloads the page on success', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK); + + actFn(); + await waitForPromises(); + + expect(window.location.reload).toHaveBeenCalled(); + }); + + it('shows an alert on error', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_INTERNAL_SERVER_ERROR); + + actFn(); + await waitForPromises(); + + expect(createAlert).toHaveBeenCalledWith( + expect.objectContaining({ + message: s__( + 'NorthstarNavigation|Could not update the new navigation preference. Please try again later.', + ), + }), + ); + expect(window.location.reload).not.toHaveBeenCalled(); + }); + + it('changes the toggle', async () => { + await actFn(); + + expect(findToggle().props('value')).toBe(!toggleValue); + }); + + it('tracks the Snowplow event', async () => { + mock.onPut(TEST_ENDPONT).reply(HTTP_STATUS_OK); + await actFn(); + await waitForPromises(); + expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_toggle', { + label: trackingLabel, + property: trackingProperty, + }); + }); + + afterEach(() => { + mock.restore(); + }); }); }); }); diff --git a/spec/frontend/nav/components/responsive_app_spec.js b/spec/frontend/nav/components/responsive_app_spec.js index 76b8ebdc92f..9d3b43520ec 100644 --- a/spec/frontend/nav/components/responsive_app_spec.js +++ b/spec/frontend/nav/components/responsive_app_spec.js @@ -33,10 +33,6 @@ describe('~/nav/components/responsive_app.vue', () => { document.body.className = 'test-class'; }); - afterEach(() => { - wrapper.destroy(); - }); - describe('default', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/nav/components/responsive_header_spec.js b/spec/frontend/nav/components/responsive_header_spec.js index f87de0afb14..2514035270a 100644 --- a/spec/frontend/nav/components/responsive_header_spec.js +++ b/spec/frontend/nav/components/responsive_header_spec.js @@ -14,7 +14,7 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { default: TEST_SLOT_CONTENT, }, directives: { - GlTooltip: createMockDirective(), + GlTooltip: createMockDirective('gl-tooltip'), }, }); }; @@ -25,10 +25,6 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { createComponent(); }); - afterEach(() => { - wrapper.destroy(); - }); - it('renders slot', () => { expect(wrapper.text()).toBe(TEST_SLOT_CONTENT); }); diff --git a/spec/frontend/nav/components/responsive_home_spec.js b/spec/frontend/nav/components/responsive_home_spec.js index 8f198d92747..5a5cfc93607 100644 --- a/spec/frontend/nav/components/responsive_home_spec.js +++ b/spec/frontend/nav/components/responsive_home_spec.js @@ -29,7 +29,7 @@ describe('~/nav/components/responsive_home.vue', () => { ...props, }, directives: { - GlTooltip: createMockDirective(), + GlTooltip: createMockDirective('gl-tooltip'), }, listeners: { 'menu-item-click': menuItemClickListener, @@ -45,10 +45,6 @@ describe('~/nav/components/responsive_home.vue', () => { menuItemClickListener = jest.fn(); }); - afterEach(() => { - wrapper.destroy(); - }); - describe('default', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/nav/components/top_nav_app_spec.js b/spec/frontend/nav/components/top_nav_app_spec.js index e70f70afc97..7f39552eb42 100644 --- a/spec/frontend/nav/components/top_nav_app_spec.js +++ b/spec/frontend/nav/components/top_nav_app_spec.js @@ -28,10 +28,6 @@ describe('~/nav/components/top_nav_app.vue', () => { const findNavItemDropdowToggle = () => findNavItemDropdown().find('.js-top-nav-dropdown-toggle'); const findMenu = () => wrapper.findComponent(TopNavDropdownMenu); - afterEach(() => { - wrapper.destroy(); - }); - describe('default', () => { beforeEach(() => { createComponentShallow(); diff --git a/spec/frontend/nav/components/top_nav_container_view_spec.js b/spec/frontend/nav/components/top_nav_container_view_spec.js index 293fe361fa9..388ac243648 100644 --- a/spec/frontend/nav/components/top_nav_container_view_spec.js +++ b/spec/frontend/nav/components/top_nav_container_view_spec.js @@ -48,10 +48,6 @@ describe('~/nav/components/top_nav_container_view.vue', () => { }; const findFrequentItemsContainer = () => wrapper.find('[data-testid="frequent-items-container"]'); - afterEach(() => { - wrapper.destroy(); - }); - it.each(['projects', 'groups'])( 'emits frequent items event to event hub (%s)', async (frequentItemsDropdownType) => { diff --git a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js index 8a0340087ec..08d6650b5bb 100644 --- a/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js +++ b/spec/frontend/nav/components/top_nav_dropdown_menu_spec.js @@ -36,10 +36,6 @@ describe('~/nav/components/top_nav_dropdown_menu.vue', () => { active: idx === activeIndex, })); - afterEach(() => { - wrapper.destroy(); - }); - beforeEach(() => { jest.spyOn(console, 'error').mockImplementation(); }); diff --git a/spec/frontend/nav/components/top_nav_menu_sections_spec.js b/spec/frontend/nav/components/top_nav_menu_sections_spec.js index 7a5a8475ab7..7a3e58fd964 100644 --- a/spec/frontend/nav/components/top_nav_menu_sections_spec.js +++ b/spec/frontend/nav/components/top_nav_menu_sections_spec.js @@ -54,10 +54,6 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { menuItems: findMenuItemModels(x), })); - afterEach(() => { - wrapper.destroy(); - }); - describe('default', () => { beforeEach(() => { createComponent(); diff --git a/spec/frontend/nav/components/top_nav_new_dropdown_spec.js b/spec/frontend/nav/components/top_nav_new_dropdown_spec.js index 18210658b89..2cd65307b0b 100644 --- a/spec/frontend/nav/components/top_nav_new_dropdown_spec.js +++ b/spec/frontend/nav/components/top_nav_new_dropdown_spec.js @@ -1,6 +1,8 @@ import { GlDropdown } from '@gitlab/ui'; import { shallowMount } from '@vue/test-utils'; import TopNavNewDropdown from '~/nav/components/top_nav_new_dropdown.vue'; +import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue'; +import { TOP_NAV_INVITE_MEMBERS_COMPONENT } from '~/invite_members/constants'; const TEST_VIEW_MODEL = { title: 'Dropdown', @@ -18,6 +20,16 @@ const TEST_VIEW_MODEL = { menu_items: [ { id: 'bar-1', title: 'Bar 1', href: '/bar/1' }, { id: 'bar-2', title: 'Bar 2', href: '/bar/2' }, + { + id: 'invite', + title: '_invite members title_', + component: TOP_NAV_INVITE_MEMBERS_COMPONENT, + icon: '_icon_', + data: { + trigger_element: '_trigger_element_', + trigger_source: '_trigger_source_', + }, + }, ], }, ], @@ -36,6 +48,7 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { }; const findDropdown = () => wrapper.findComponent(GlDropdown); + const findInviteMembersTrigger = () => wrapper.findComponent(InviteMembersTrigger); const findDropdownContents = () => findDropdown() .findAll('[data-testid]') @@ -55,10 +68,6 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { }; }); - afterEach(() => { - wrapper.destroy(); - }); - describe('default', () => { beforeEach(() => { createComponent(); @@ -73,6 +82,10 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { }); it('renders dropdown content', () => { + const hrefItems = TEST_VIEW_MODEL.menu_sections[1].menu_items.filter((item) => + Boolean(item.href), + ); + expect(findDropdownContents()).toEqual([ { type: 'header', @@ -90,12 +103,18 @@ describe('~/nav/components/top_nav_menu_sections.vue', () => { type: 'header', text: TEST_VIEW_MODEL.menu_sections[1].title, }, - ...TEST_VIEW_MODEL.menu_sections[1].menu_items.map(({ title, href }) => ({ + ...hrefItems.map(({ title, href }) => ({ type: 'item', href, text: title, })), ]); + expect(findInviteMembersTrigger().props()).toMatchObject({ + displayText: '_invite members title_', + icon: '_icon_', + triggerElement: 'dropdown-_trigger_element_', + triggerSource: '_trigger_source_', + }); }); }); |