diff options
Diffstat (limited to 'spec/frontend/jira_connect')
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js | 44 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js | 36 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js (renamed from spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js) | 4 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js (renamed from spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js) | 6 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/app_spec.js | 176 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js | 48 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js | 50 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/index_spec.js | 36 | ||||
-rw-r--r-- | spec/frontend/jira_connect/subscriptions/utils_spec.js | 22 |
9 files changed, 304 insertions, 118 deletions
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js new file mode 100644 index 00000000000..5ec1b7b7932 --- /dev/null +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_button_spec.js @@ -0,0 +1,44 @@ +import { GlButton } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue'; +import AddNamespaceModal from '~/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue'; +import { ADD_NAMESPACE_MODAL_ID } from '~/jira_connect/subscriptions/constants'; +import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; + +describe('AddNamespaceButton', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(AddNamespaceButton, { + directives: { + glModal: createMockDirective(), + }, + }); + }; + + const findButton = () => wrapper.findComponent(GlButton); + const findModal = () => wrapper.findComponent(AddNamespaceModal); + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('displays a button', () => { + expect(findButton().exists()).toBe(true); + }); + + it('contains a modal', () => { + expect(findModal().exists()).toBe(true); + }); + + it('button is bound to the modal', () => { + const { value } = getBinding(findButton().element, 'gl-modal'); + + expect(value).toBeTruthy(); + expect(value).toBe(ADD_NAMESPACE_MODAL_ID); + }); +}); diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js new file mode 100644 index 00000000000..d80381107f2 --- /dev/null +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal_spec.js @@ -0,0 +1,36 @@ +import { shallowMount } from '@vue/test-utils'; +import AddNamespaceModal from '~/jira_connect/subscriptions/components/add_namespace_modal/add_namespace_modal.vue'; +import GroupsList from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue'; +import { ADD_NAMESPACE_MODAL_ID } from '~/jira_connect/subscriptions/constants'; + +describe('AddNamespaceModal', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(AddNamespaceModal); + }; + + const findModal = () => wrapper.findComponent(AddNamespaceModal); + const findGroupsList = () => wrapper.findComponent(GroupsList); + + beforeEach(() => { + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('displays modal with correct props', () => { + const modal = findModal(); + expect(modal.exists()).toBe(true); + expect(modal.attributes()).toMatchObject({ + modalid: ADD_NAMESPACE_MODAL_ID, + title: AddNamespaceModal.modal.title, + }); + }); + + it('displays GroupList', () => { + expect(findGroupsList().exists()).toBe(true); + }); +}); diff --git a/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js index b69435df83a..15e9a740c83 100644 --- a/spec/frontend/jira_connect/subscriptions/components/groups_list_item_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js @@ -4,9 +4,9 @@ import waitForPromises from 'helpers/wait_for_promises'; import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue'; -import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue'; +import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue'; import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils'; -import { mockGroup1 } from '../mock_data'; +import { mockGroup1 } from '../../mock_data'; jest.mock('~/jira_connect/subscriptions/utils'); diff --git a/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js index d3a9a3bfd41..04aba8bda23 100644 --- a/spec/frontend/jira_connect/subscriptions/components/groups_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_spec.js @@ -3,10 +3,10 @@ import { shallowMount } from '@vue/test-utils'; import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import { fetchGroups } from '~/jira_connect/subscriptions/api'; -import GroupsList from '~/jira_connect/subscriptions/components/groups_list.vue'; -import GroupsListItem from '~/jira_connect/subscriptions/components/groups_list_item.vue'; +import GroupsList from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list.vue'; +import GroupsListItem from '~/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item.vue'; import { DEFAULT_GROUPS_PER_PAGE } from '~/jira_connect/subscriptions/constants'; -import { mockGroup1, mockGroup2 } from '../mock_data'; +import { mockGroup1, mockGroup2 } from '../../mock_data'; const createMockGroup = (groupId) => { return { diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js index 8915a7697a5..8e464968453 100644 --- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js @@ -1,14 +1,17 @@ -import { GlAlert, GlButton, GlModal, GlLink } from '@gitlab/ui'; +import { GlAlert, GlLink, GlEmptyState } from '@gitlab/ui'; import { mount, shallowMount } from '@vue/test-utils'; import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue'; +import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue'; +import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue'; +import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue'; import createStore from '~/jira_connect/subscriptions/store'; import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; import { __ } from '~/locale'; +import { mockSubscription } from '../mock_data'; jest.mock('~/jira_connect/subscriptions/utils', () => ({ retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }), - getLocation: jest.fn(), })); describe('JiraConnectApp', () => { @@ -17,8 +20,10 @@ describe('JiraConnectApp', () => { const findAlert = () => wrapper.findComponent(GlAlert); const findAlertLink = () => findAlert().findComponent(GlLink); - const findGlButton = () => wrapper.findComponent(GlButton); - const findGlModal = () => wrapper.findComponent(GlModal); + const findSignInButton = () => wrapper.findComponent(SignInButton); + const findAddNamespaceButton = () => wrapper.findComponent(AddNamespaceButton); + const findSubscriptionsList = () => wrapper.findComponent(SubscriptionsList); + const findEmptyState = () => wrapper.findComponent(GlEmptyState); const createComponent = ({ provide, mountFn = shallowMount } = {}) => { store = createStore(); @@ -34,96 +39,115 @@ describe('JiraConnectApp', () => { }); describe('template', () => { - describe('when user is not logged in', () => { - beforeEach(() => { - createComponent({ - provide: { - usersPath: '/users', - }, + describe.each` + scenario | usersPath | subscriptions | expectSignInButton | expectEmptyState | expectNamespaceButton | expectSubscriptionsList + ${'user is not signed in with subscriptions'} | ${'/users'} | ${[mockSubscription]} | ${true} | ${false} | ${false} | ${true} + ${'user is not signed in without subscriptions'} | ${'/users'} | ${undefined} | ${true} | ${false} | ${false} | ${false} + ${'user is signed in with subscriptions'} | ${undefined} | ${[mockSubscription]} | ${false} | ${false} | ${true} | ${true} + ${'user is signed in without subscriptions'} | ${undefined} | ${undefined} | ${false} | ${true} | ${false} | ${false} + `( + 'when $scenario', + ({ + usersPath, + expectSignInButton, + subscriptions, + expectEmptyState, + expectNamespaceButton, + expectSubscriptionsList, + }) => { + beforeEach(() => { + createComponent({ + provide: { + usersPath, + subscriptions, + }, + }); }); - }); - it('renders "Sign in" button', () => { - expect(findGlButton().text()).toBe('Sign in to add namespaces'); - expect(findGlModal().exists()).toBe(false); - }); - }); + it(`${expectSignInButton ? 'renders' : 'does not render'} sign in button`, () => { + expect(findSignInButton().exists()).toBe(expectSignInButton); + }); - describe('when user is logged in', () => { - beforeEach(() => { - createComponent(); - }); + it(`${expectEmptyState ? 'renders' : 'does not render'} empty state`, () => { + expect(findEmptyState().exists()).toBe(expectEmptyState); + }); - it('renders "Add" button and modal', () => { - expect(findGlButton().text()).toBe('Add namespace'); - expect(findGlModal().exists()).toBe(true); - }); - }); + it(`${ + expectNamespaceButton ? 'renders' : 'does not render' + } button to add namespace`, () => { + expect(findAddNamespaceButton().exists()).toBe(expectNamespaceButton); + }); + + it(`${expectSubscriptionsList ? 'renders' : 'does not render'} subscriptions list`, () => { + expect(findSubscriptionsList().exists()).toBe(expectSubscriptionsList); + }); + }, + ); + }); - describe('alert', () => { - it.each` - message | variant | alertShouldRender - ${'Test error'} | ${'danger'} | ${true} - ${'Test notice'} | ${'info'} | ${true} - ${''} | ${undefined} | ${false} - ${undefined} | ${undefined} | ${false} - `( - 'renders correct alert when message is `$message` and variant is `$variant`', - async ({ message, alertShouldRender, variant }) => { - createComponent(); - - store.commit(SET_ALERT, { message, variant }); - await wrapper.vm.$nextTick(); - - const alert = findAlert(); - - expect(alert.exists()).toBe(alertShouldRender); - if (alertShouldRender) { - expect(alert.isVisible()).toBe(alertShouldRender); - expect(alert.html()).toContain(message); - expect(alert.props('variant')).toBe(variant); - expect(findAlertLink().exists()).toBe(false); - } - }, - ); - - it('hides alert on @dismiss event', async () => { + describe('alert', () => { + it.each` + message | variant | alertShouldRender + ${'Test error'} | ${'danger'} | ${true} + ${'Test notice'} | ${'info'} | ${true} + ${''} | ${undefined} | ${false} + ${undefined} | ${undefined} | ${false} + `( + 'renders correct alert when message is `$message` and variant is `$variant`', + async ({ message, alertShouldRender, variant }) => { createComponent(); - store.commit(SET_ALERT, { message: 'test message' }); + store.commit(SET_ALERT, { message, variant }); await wrapper.vm.$nextTick(); - findAlert().vm.$emit('dismiss'); - await wrapper.vm.$nextTick(); + const alert = findAlert(); - expect(findAlert().exists()).toBe(false); - }); + expect(alert.exists()).toBe(alertShouldRender); + if (alertShouldRender) { + expect(alert.isVisible()).toBe(alertShouldRender); + expect(alert.html()).toContain(message); + expect(alert.props('variant')).toBe(variant); + expect(findAlertLink().exists()).toBe(false); + } + }, + ); - it('renders link when `linkUrl` is set', async () => { - createComponent({ mountFn: mount }); + it('hides alert on @dismiss event', async () => { + createComponent(); - store.commit(SET_ALERT, { - message: __('test message %{linkStart}test link%{linkEnd}'), - linkUrl: 'https://gitlab.com', - }); - await wrapper.vm.$nextTick(); + store.commit(SET_ALERT, { message: 'test message' }); + await wrapper.vm.$nextTick(); + + findAlert().vm.$emit('dismiss'); + await wrapper.vm.$nextTick(); + + expect(findAlert().exists()).toBe(false); + }); - const alertLink = findAlertLink(); + it('renders link when `linkUrl` is set', async () => { + createComponent({ mountFn: mount }); - expect(alertLink.exists()).toBe(true); - expect(alertLink.text()).toContain('test link'); - expect(alertLink.attributes('href')).toBe('https://gitlab.com'); + store.commit(SET_ALERT, { + message: __('test message %{linkStart}test link%{linkEnd}'), + linkUrl: 'https://gitlab.com', }); + await wrapper.vm.$nextTick(); - describe('when alert is set in localStoage', () => { - it('renders alert on mount', () => { - createComponent(); + const alertLink = findAlertLink(); - const alert = findAlert(); + expect(alertLink.exists()).toBe(true); + expect(alertLink.text()).toContain('test link'); + expect(alertLink.attributes('href')).toBe('https://gitlab.com'); + }); - expect(alert.exists()).toBe(true); - expect(alert.html()).toContain('error message'); - }); + describe('when alert is set in localStoage', () => { + it('renders alert on mount', () => { + createComponent(); + + const alert = findAlert(); + + expect(alert.exists()).toBe(true); + expect(alert.html()).toContain('error message'); }); }); }); diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js new file mode 100644 index 00000000000..cb5ae877c47 --- /dev/null +++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_button_spec.js @@ -0,0 +1,48 @@ +import { GlButton } from '@gitlab/ui'; +import { shallowMount } from '@vue/test-utils'; +import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils'; +import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue'; +import waitForPromises from 'helpers/wait_for_promises'; + +const MOCK_USERS_PATH = '/user'; + +jest.mock('~/jira_connect/subscriptions/utils'); + +describe('SignInButton', () => { + let wrapper; + + const createComponent = () => { + wrapper = shallowMount(SignInButton, { + propsData: { + usersPath: MOCK_USERS_PATH, + }, + }); + }; + + const findButton = () => wrapper.findComponent(GlButton); + + afterEach(() => { + wrapper.destroy(); + }); + + it('displays a button', () => { + createComponent(); + + expect(findButton().exists()).toBe(true); + }); + + describe.each` + expectedHref + ${MOCK_USERS_PATH} + ${`${MOCK_USERS_PATH}?return_to=${encodeURIComponent('https://test.jira.com')}`} + `('when getGitlabSignInURL resolves with `$expectedHref`', ({ expectedHref }) => { + it(`sets button href to ${expectedHref}`, async () => { + getGitlabSignInURL.mockResolvedValue(expectedHref); + createComponent(); + + await waitForPromises(); + + expect(findButton().attributes('href')).toBe(expectedHref); + }); + }); +}); diff --git a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js index 32b43765843..4e4a2b58600 100644 --- a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js @@ -1,12 +1,15 @@ -import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui'; -import { mount, shallowMount } from '@vue/test-utils'; +import { GlButton } from '@gitlab/ui'; +import { mount } from '@vue/test-utils'; import waitForPromises from 'helpers/wait_for_promises'; import * as JiraConnectApi from '~/jira_connect/subscriptions/api'; +import GroupItemName from '~/jira_connect/subscriptions/components/group_item_name.vue'; + import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue'; import createStore from '~/jira_connect/subscriptions/store'; import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; import { reloadPage } from '~/jira_connect/subscriptions/utils'; +import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import { mockSubscription } from '../mock_data'; jest.mock('~/jira_connect/subscriptions/utils'); @@ -15,11 +18,13 @@ describe('SubscriptionsList', () => { let wrapper; let store; - const createComponent = ({ mountFn = shallowMount, provide = {} } = {}) => { + const createComponent = () => { store = createStore(); - wrapper = mountFn(SubscriptionsList, { - provide, + wrapper = mount(SubscriptionsList, { + provide: { + subscriptions: [mockSubscription], + }, store, }); }; @@ -28,28 +33,28 @@ describe('SubscriptionsList', () => { wrapper.destroy(); }); - const findGlEmptyState = () => wrapper.findComponent(GlEmptyState); - const findGlTable = () => wrapper.findComponent(GlTable); - const findUnlinkButton = () => findGlTable().findComponent(GlButton); + const findUnlinkButton = () => wrapper.findComponent(GlButton); const clickUnlinkButton = () => findUnlinkButton().trigger('click'); describe('template', () => { - it('renders GlEmptyState when subscriptions is empty', () => { + beforeEach(() => { createComponent(); + }); + + it('renders "name" cell correctly', () => { + const groupItemNames = wrapper.findAllComponents(GroupItemName); + expect(groupItemNames.wrappers).toHaveLength(1); - expect(findGlEmptyState().exists()).toBe(true); - expect(findGlTable().exists()).toBe(false); + const item = groupItemNames.at(0); + expect(item.props('group')).toBe(mockSubscription.group); }); - it('renders GlTable when subscriptions are present', () => { - createComponent({ - provide: { - subscriptions: [mockSubscription], - }, - }); + it('renders "created at" cell correctly', () => { + const timeAgoTooltips = wrapper.findAllComponents(TimeagoTooltip); + expect(timeAgoTooltips.wrappers).toHaveLength(1); - expect(findGlEmptyState().exists()).toBe(false); - expect(findGlTable().exists()).toBe(true); + const item = timeAgoTooltips.at(0); + expect(item.props('time')).toBe(mockSubscription.created_at); }); }); @@ -57,12 +62,7 @@ describe('SubscriptionsList', () => { let removeSubscriptionSpy; beforeEach(() => { - createComponent({ - mountFn: mount, - provide: { - subscriptions: [mockSubscription], - }, - }); + createComponent(); removeSubscriptionSpy = jest.spyOn(JiraConnectApi, 'removeSubscription').mockResolvedValue(); }); diff --git a/spec/frontend/jira_connect/subscriptions/index_spec.js b/spec/frontend/jira_connect/subscriptions/index_spec.js index 786f3b4a7d3..b97918a198e 100644 --- a/spec/frontend/jira_connect/subscriptions/index_spec.js +++ b/spec/frontend/jira_connect/subscriptions/index_spec.js @@ -1,24 +1,36 @@ import { initJiraConnect } from '~/jira_connect/subscriptions'; +import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils'; -jest.mock('~/jira_connect/subscriptions/utils', () => ({ - getLocation: jest.fn().mockResolvedValue('test/location'), -})); +jest.mock('~/jira_connect/subscriptions/utils'); describe('initJiraConnect', () => { - beforeEach(async () => { + const mockInitialHref = 'https://gitlab.com'; + + beforeEach(() => { setFixtures(` - <a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a> - <a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a> + <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Sign In</a> + <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Another Sign In</a> `); - - await initJiraConnect(); }); + const assertSignInLinks = (expectedLink) => { + Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => { + expect(el.getAttribute('href')).toBe(expectedLink); + }); + }; + describe('Sign in links', () => { - it('have `return_to` query parameter', () => { - Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => { - expect(el.href).toContain('return_to=test/location'); - }); + it('are updated on initialization', async () => { + const mockSignInLink = `https://gitlab.com?return_to=${encodeURIComponent('/test/location')}`; + getGitlabSignInURL.mockResolvedValue(mockSignInLink); + + // assert the initial state + assertSignInLinks(mockInitialHref); + + await initJiraConnect(); + + // assert the update has occurred + assertSignInLinks(mockSignInLink); }); }); }); diff --git a/spec/frontend/jira_connect/subscriptions/utils_spec.js b/spec/frontend/jira_connect/subscriptions/utils_spec.js index 2dd95de1b8c..762d9eb3443 100644 --- a/spec/frontend/jira_connect/subscriptions/utils_spec.js +++ b/spec/frontend/jira_connect/subscriptions/utils_spec.js @@ -8,6 +8,7 @@ import { getLocation, reloadPage, sizeToParent, + getGitlabSignInURL, } from '~/jira_connect/subscriptions/utils'; describe('JiraConnect utils', () => { @@ -137,4 +138,25 @@ describe('JiraConnect utils', () => { }); }); }); + + describe('getGitlabSignInURL', () => { + const mockSignInURL = 'https://gitlab.com/sign_in'; + + it.each` + returnTo | expectResult + ${undefined} | ${mockSignInURL} + ${''} | ${mockSignInURL} + ${'/test/location'} | ${`${mockSignInURL}?return_to=${encodeURIComponent('/test/location')}`} + `( + 'returns `$expectResult` when `AP.getLocation` resolves to `$returnTo`', + async ({ returnTo, expectResult }) => { + global.AP = { + getLocation: jest.fn().mockImplementation((cb) => cb(returnTo)), + }; + + const url = await getGitlabSignInURL(mockSignInURL); + expect(url).toBe(expectResult); + }, + ); + }); }); |