diff options
Diffstat (limited to 'spec/frontend/jira_connect/subscriptions/components')
4 files changed, 135 insertions, 90 deletions
diff --git a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js index 3d7bf7acb41..5df54abfc05 100644 --- a/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/add_namespace_modal/groups_list_item_spec.js @@ -7,21 +7,35 @@ 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/add_namespace_modal/groups_list_item.vue'; import { persistAlert, reloadPage } from '~/jira_connect/subscriptions/utils'; +import { + I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, + I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, + INTEGRATIONS_DOC_LINK, +} from '~/jira_connect/subscriptions/constants'; +import createStore from '~/jira_connect/subscriptions/store'; import { mockGroup1 } from '../../mock_data'; jest.mock('~/jira_connect/subscriptions/utils'); describe('GroupsListItem', () => { let wrapper; - const mockSubscriptionPath = 'subscriptionPath'; + let store; + + const mockAddSubscriptionsPath = '/addSubscriptionsPath'; + + const createComponent = ({ mountFn = shallowMount, provide } = {}) => { + store = createStore(); + + jest.spyOn(store, 'dispatch').mockImplementation(); - const createComponent = ({ mountFn = shallowMount } = {}) => { wrapper = mountFn(GroupsListItem, { + store, propsData: { group: mockGroup1, }, provide: { - subscriptionsPath: mockSubscriptionPath, + addSubscriptionsPath: mockAddSubscriptionsPath, + ...provide, }, }); }; @@ -51,62 +65,88 @@ describe('GroupsListItem', () => { }); describe('on Link button click', () => { - let addSubscriptionSpy; + describe('when jiraConnectOauth feature flag is disabled', () => { + let addSubscriptionSpy; - beforeEach(() => { - createComponent({ mountFn: mount }); + beforeEach(() => { + createComponent({ mountFn: mount }); - addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue(); - }); + addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue(); + }); - it('sets button to loading and sends request', async () => { - expect(findLinkButton().props('loading')).toBe(false); + it('sets button to loading and sends request', async () => { + expect(findLinkButton().props('loading')).toBe(false); + + clickLinkButton(); + await nextTick(); - clickLinkButton(); + expect(findLinkButton().props('loading')).toBe(true); + await waitForPromises(); - await nextTick(); + expect(addSubscriptionSpy).toHaveBeenCalledWith( + mockAddSubscriptionsPath, + mockGroup1.full_path, + ); + expect(persistAlert).toHaveBeenCalledWith({ + linkUrl: INTEGRATIONS_DOC_LINK, + message: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_MESSAGE, + title: I18N_ADD_SUBSCRIPTION_SUCCESS_ALERT_TITLE, + variant: 'success', + }); + }); - expect(findLinkButton().props('loading')).toBe(true); + describe('when request is successful', () => { + it('reloads the page', async () => { + clickLinkButton(); - await waitForPromises(); + await waitForPromises(); - expect(addSubscriptionSpy).toHaveBeenCalledWith(mockSubscriptionPath, mockGroup1.full_path); - expect(persistAlert).toHaveBeenCalledWith({ - linkUrl: '/help/integration/jira_development_panel.html#use-the-integration', - message: - 'You should now see GitLab.com activity inside your Jira Cloud issues. %{linkStart}Learn more%{linkEnd}', - title: 'Namespace successfully linked', - variant: 'success', + expect(reloadPage).toHaveBeenCalled(); + }); }); - }); - describe('when request is successful', () => { - it('reloads the page', async () => { - clickLinkButton(); + describe('when request has errors', () => { + const mockErrorMessage = 'error message'; + const mockError = { response: { data: { error: mockErrorMessage } } }; - await waitForPromises(); + beforeEach(() => { + addSubscriptionSpy = jest + .spyOn(JiraConnectApi, 'addSubscription') + .mockRejectedValue(mockError); + }); - expect(reloadPage).toHaveBeenCalled(); + it('emits `error` event', async () => { + clickLinkButton(); + + await waitForPromises(); + + expect(reloadPage).not.toHaveBeenCalled(); + expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage); + }); }); }); - describe('when request has errors', () => { - const mockErrorMessage = 'error message'; - const mockError = { response: { data: { error: mockErrorMessage } } }; + describe('when jiraConnectOauth feature flag is enabled', () => { + const mockSubscriptionsPath = '/subscriptions'; beforeEach(() => { - addSubscriptionSpy = jest - .spyOn(JiraConnectApi, 'addSubscription') - .mockRejectedValue(mockError); + createComponent({ + mountFn: mount, + provide: { + subscriptionsPath: mockSubscriptionsPath, + glFeatures: { jiraConnectOauth: true }, + }, + }); }); - it('emits `error` event', async () => { + it('dispatches `addSubscription` action', async () => { clickLinkButton(); + await nextTick(); - await waitForPromises(); - - expect(reloadPage).not.toHaveBeenCalled(); - expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage); + expect(store.dispatch).toHaveBeenCalledWith('addSubscription', { + namespacePath: mockGroup1.full_path, + subscriptionsPath: mockSubscriptionsPath, + }); }); }); }); diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js index ce02144f22f..9894141be5a 100644 --- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js @@ -3,8 +3,8 @@ import { nextTick } from 'vue'; import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper'; import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue'; -import SignInPage from '~/jira_connect/subscriptions/pages/sign_in.vue'; -import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions.vue'; +import SignInPage from '~/jira_connect/subscriptions/pages/sign_in/sign_in_page.vue'; +import SubscriptionsPage from '~/jira_connect/subscriptions/pages/subscriptions_page.vue'; import UserLink from '~/jira_connect/subscriptions/components/user_link.vue'; import BrowserSupportAlert from '~/jira_connect/subscriptions/components/browser_support_alert.vue'; import createStore from '~/jira_connect/subscriptions/store'; @@ -12,6 +12,7 @@ import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types'; import { I18N_DEFAULT_SIGN_IN_ERROR_MESSAGE } from '~/jira_connect/subscriptions/constants'; import { __ } from '~/locale'; import AccessorUtilities from '~/lib/utils/accessor'; +import * as api from '~/jira_connect/subscriptions/api'; import { mockSubscription } from '../mock_data'; jest.mock('~/jira_connect/subscriptions/utils', () => ({ @@ -31,7 +32,8 @@ describe('JiraConnectApp', () => { const findBrowserSupportAlert = () => wrapper.findComponent(BrowserSupportAlert); const createComponent = ({ provide, mountFn = shallowMountExtended } = {}) => { - store = createStore(); + store = createStore({ subscriptions: [mockSubscription] }); + jest.spyOn(store, 'dispatch').mockImplementation(); wrapper = mountFn(JiraConnectApp, { store, @@ -53,7 +55,6 @@ describe('JiraConnectApp', () => { createComponent({ provide: { usersPath, - subscriptions: [mockSubscription], }, }); }); @@ -79,14 +80,13 @@ describe('JiraConnectApp', () => { createComponent({ provide: { usersPath: '/user', - subscriptions: [], }, }); const userLink = findUserLink(); expect(userLink.exists()).toBe(true); expect(userLink.props()).toEqual({ - hasSubscriptions: false, + hasSubscriptions: true, user: null, userSignedIn: false, }); @@ -161,39 +161,11 @@ describe('JiraConnectApp', () => { }); describe('when user signed out', () => { - describe('when sign in page emits `sign-in-oauth` event', () => { - const mockUser = { name: 'test' }; - beforeEach(async () => { - createComponent({ - provide: { - usersPath: '/mock', - subscriptions: [], - }, - }); - findSignInPage().vm.$emit('sign-in-oauth', mockUser); - - await nextTick(); - }); - - it('hides sign in page and renders subscriptions page', () => { - expect(findSignInPage().exists()).toBe(false); - expect(findSubscriptionsPage().exists()).toBe(true); - }); - - it('sets correct UserLink props', () => { - expect(findUserLink().props()).toMatchObject({ - user: mockUser, - userSignedIn: true, - }); - }); - }); - describe('when sign in page emits `error` event', () => { beforeEach(async () => { createComponent({ provide: { usersPath: '/mock', - subscriptions: [], }, }); findSignInPage().vm.$emit('error'); @@ -235,4 +207,31 @@ describe('JiraConnectApp', () => { }); }, ); + + describe('when `jiraConnectOauth` feature flag is enabled', () => { + const mockSubscriptionsPath = '/mockSubscriptionsPath'; + + beforeEach(() => { + jest.spyOn(api, 'fetchSubscriptions').mockResolvedValue({ data: { subscriptions: [] } }); + + createComponent({ + provide: { + glFeatures: { jiraConnectOauth: true }, + subscriptionsPath: mockSubscriptionsPath, + }, + }); + }); + + describe('when component mounts', () => { + it('dispatches `fetchSubscriptions` action', async () => { + expect(store.dispatch).toHaveBeenCalledWith('fetchSubscriptions', mockSubscriptionsPath); + }); + }); + + describe('when oauth button emits `sign-in-oauth` event', () => { + it('dispatches `fetchSubscriptions` action', () => { + expect(store.dispatch).toHaveBeenCalledWith('fetchSubscriptions', mockSubscriptionsPath); + }); + }); + }); }); diff --git a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js index 18274cd4362..8730e124ae7 100644 --- a/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/sign_in_oauth_button_spec.js @@ -11,9 +11,14 @@ import axios from '~/lib/utils/axios_utils'; import waitForPromises from 'helpers/wait_for_promises'; import httpStatus from '~/lib/utils/http_status'; import AccessorUtilities from '~/lib/utils/accessor'; +import { getCurrentUser } from '~/rest_api'; +import createStore from '~/jira_connect/subscriptions/store'; +import { SET_ACCESS_TOKEN } from '~/jira_connect/subscriptions/store/mutation_types'; jest.mock('~/lib/utils/accessor'); jest.mock('~/jira_connect/subscriptions/utils'); +jest.mock('~/jira_connect/subscriptions/api'); +jest.mock('~/rest_api'); jest.mock('~/jira_connect/subscriptions/pkce', () => ({ createCodeVerifier: jest.fn().mockReturnValue('mock-verifier'), createCodeChallenge: jest.fn().mockResolvedValue('mock-challenge'), @@ -28,9 +33,15 @@ const mockOauthMetadata = { describe('SignInOauthButton', () => { let wrapper; let mockAxios; + let store; const createComponent = ({ slots } = {}) => { + store = createStore(); + jest.spyOn(store, 'dispatch').mockImplementation(); + jest.spyOn(store, 'commit').mockImplementation(); + wrapper = shallowMount(SignInOauthButton, { + store, slots, provide: { oauthMetadata: mockOauthMetadata, @@ -114,10 +125,6 @@ describe('SignInOauthButton', () => { await waitForPromises(); }); - it('emits `error` event', () => { - expect(wrapper.emitted('error')).toBeTruthy(); - }); - it('does not emit `sign-in` event', () => { expect(wrapper.emitted('sign-in')).toBeFalsy(); }); @@ -147,7 +154,7 @@ describe('SignInOauthButton', () => { mockAxios .onPost(mockOauthMetadata.oauth_token_url) .replyOnce(httpStatus.OK, { access_token: mockAccessToken }); - mockAxios.onGet('/api/v4/user').replyOnce(httpStatus.OK, mockUser); + getCurrentUser.mockResolvedValue({ data: mockUser }); window.dispatchEvent(new MessageEvent('message', mockEvent)); @@ -161,25 +168,25 @@ describe('SignInOauthButton', () => { }); }); - it('executes GET request to fetch user data', () => { - expect(axios.get).toHaveBeenCalledWith('/api/v4/user', { - headers: { Authorization: `Bearer ${mockAccessToken}` }, - }); + it('dispatches loadCurrentUser action', () => { + expect(store.dispatch).toHaveBeenCalledWith('loadCurrentUser', mockAccessToken); + }); + + it('commits SET_ACCESS_TOKEN mutation with correct access token', () => { + expect(store.commit).toHaveBeenCalledWith(SET_ACCESS_TOKEN, mockAccessToken); }); it('emits `sign-in` event with user data', () => { - expect(wrapper.emitted('sign-in')[0]).toEqual([mockUser]); + expect(wrapper.emitted('sign-in')[0]).toBeTruthy(); }); }); describe('when API requests fail', () => { beforeEach(async () => { jest.spyOn(axios, 'post'); - jest.spyOn(axios, 'get'); mockAxios .onPost(mockOauthMetadata.oauth_token_url) - .replyOnce(httpStatus.INTERNAL_SERVER_ERROR, { access_token: mockAccessToken }); - mockAxios.onGet('/api/v4/user').replyOnce(httpStatus.INTERNAL_SERVER_ERROR, mockUser); + .replyOnce(httpStatus.INTERNAL_SERVER_ERROR); window.dispatchEvent(new MessageEvent('message', mockEvent)); @@ -187,7 +194,7 @@ describe('SignInOauthButton', () => { }); it('emits `error` event', () => { - expect(wrapper.emitted('error')).toBeTruthy(); + expect(wrapper.emitted('error')[0]).toEqual([]); }); it('does not emit `sign-in` event', () => { 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 2aad533f677..2d7c58fc278 100644 --- a/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js +++ b/spec/frontend/jira_connect/subscriptions/components/subscriptions_list_spec.js @@ -20,12 +20,11 @@ describe('SubscriptionsList', () => { let store; const createComponent = () => { - store = createStore(); + store = createStore({ + subscriptions: [mockSubscription], + }); wrapper = mount(SubscriptionsList, { - provide: { - subscriptions: [mockSubscription], - }, store, }); }; |