Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/jira_connect')
-rw-r--r--spec/frontend/jira_connect/api_spec.js5
-rw-r--r--spec/frontend/jira_connect/components/app_spec.js36
-rw-r--r--spec/frontend/jira_connect/components/groups_list_item_spec.js109
-rw-r--r--spec/frontend/jira_connect/components/groups_list_spec.js30
-rw-r--r--spec/frontend/jira_connect/index_spec.js56
-rw-r--r--spec/frontend/jira_connect/mock_data.js2
6 files changed, 212 insertions, 26 deletions
diff --git a/spec/frontend/jira_connect/api_spec.js b/spec/frontend/jira_connect/api_spec.js
index 8fecbee9ca7..240a57c7917 100644
--- a/spec/frontend/jira_connect/api_spec.js
+++ b/spec/frontend/jira_connect/api_spec.js
@@ -1,9 +1,8 @@
import MockAdapter from 'axios-mock-adapter';
+import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
-import { addSubscription, removeSubscription, fetchGroups } from '~/jira_connect/api';
-
describe('JiraConnect API', () => {
let mock;
let response;
@@ -14,7 +13,7 @@ describe('JiraConnect API', () => {
const mockJwt = 'jwt';
const mockResponse = { success: true };
- const tokenSpy = jest.fn().mockReturnValue(mockJwt);
+ const tokenSpy = jest.fn((callback) => callback(mockJwt));
window.AP = {
context: {
diff --git a/spec/frontend/jira_connect/components/app_spec.js b/spec/frontend/jira_connect/components/app_spec.js
index be990d5061c..d11b66b2089 100644
--- a/spec/frontend/jira_connect/components/app_spec.js
+++ b/spec/frontend/jira_connect/components/app_spec.js
@@ -1,19 +1,20 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
+import { GlAlert, GlButton, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { GlAlert } from '@gitlab/ui';
+
import JiraConnectApp from '~/jira_connect/components/app.vue';
import createStore from '~/jira_connect/store';
import { SET_ERROR_MESSAGE } from '~/jira_connect/store/mutation_types';
-Vue.use(Vuex);
+jest.mock('~/jira_connect/api');
describe('JiraConnectApp', () => {
let wrapper;
let store;
const findAlert = () => wrapper.findComponent(GlAlert);
+ const findGlButton = () => wrapper.findComponent(GlButton);
+ const findGlModal = () => wrapper.findComponent(GlModal);
const findHeader = () => wrapper.findByTestId('new-jira-connect-ui-heading');
const findHeaderText = () => findHeader().text();
@@ -44,6 +45,33 @@ describe('JiraConnectApp', () => {
expect(findHeaderText()).toBe('Linked namespaces');
});
+ describe('when user is not logged in', () => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures: { newJiraConnectUi: true },
+ usersPath: '/users',
+ },
+ });
+ });
+
+ it('renders "Sign in" button', () => {
+ expect(findGlButton().text()).toBe('Sign in to add namespaces');
+ expect(findGlModal().exists()).toBe(false);
+ });
+ });
+
+ describe('when user is logged in', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders "Add" button and modal', () => {
+ expect(findGlButton().text()).toBe('Add namespace');
+ expect(findGlModal().exists()).toBe(true);
+ });
+ });
+
describe('newJiraConnectUi is false', () => {
it('does not render new UI', () => {
createComponent({
diff --git a/spec/frontend/jira_connect/components/groups_list_item_spec.js b/spec/frontend/jira_connect/components/groups_list_item_spec.js
index 77577c53cf4..bb247534aca 100644
--- a/spec/frontend/jira_connect/components/groups_list_item_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_item_spec.js
@@ -1,27 +1,37 @@
-import { shallowMount } from '@vue/test-utils';
-import { GlAvatar } from '@gitlab/ui';
+import { GlAvatar, GlButton } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { mockGroup1 } from '../mock_data';
+import waitForPromises from 'helpers/wait_for_promises';
+import * as JiraConnectApi from '~/jira_connect/api';
import GroupsListItem from '~/jira_connect/components/groups_list_item.vue';
+import { mockGroup1 } from '../mock_data';
describe('GroupsListItem', () => {
let wrapper;
+ const mockSubscriptionPath = 'subscriptionPath';
- const createComponent = () => {
+ const reloadSpy = jest.fn();
+
+ global.AP = {
+ navigator: {
+ reload: reloadSpy,
+ },
+ };
+
+ const createComponent = ({ mountFn = shallowMount } = {}) => {
wrapper = extendedWrapper(
- shallowMount(GroupsListItem, {
+ mountFn(GroupsListItem, {
propsData: {
group: mockGroup1,
},
+ provide: {
+ subscriptionsPath: mockSubscriptionPath,
+ },
}),
);
};
- beforeEach(() => {
- createComponent();
- });
-
afterEach(() => {
wrapper.destroy();
wrapper = null;
@@ -30,17 +40,82 @@ describe('GroupsListItem', () => {
const findGlAvatar = () => wrapper.find(GlAvatar);
const findGroupName = () => wrapper.findByTestId('group-list-item-name');
const findGroupDescription = () => wrapper.findByTestId('group-list-item-description');
+ const findLinkButton = () => wrapper.find(GlButton);
+ const clickLinkButton = () => findLinkButton().trigger('click');
- it('renders group avatar', () => {
- expect(findGlAvatar().exists()).toBe(true);
- expect(findGlAvatar().props('src')).toBe(mockGroup1.avatar_url);
- });
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders group avatar', () => {
+ expect(findGlAvatar().exists()).toBe(true);
+ expect(findGlAvatar().props('src')).toBe(mockGroup1.avatar_url);
+ });
+
+ it('renders group name', () => {
+ expect(findGroupName().text()).toBe(mockGroup1.full_name);
+ });
- it('renders group name', () => {
- expect(findGroupName().text()).toBe(mockGroup1.full_name);
+ it('renders group description', () => {
+ expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ });
+
+ it('renders Link button', () => {
+ expect(findLinkButton().exists()).toBe(true);
+ expect(findLinkButton().text()).toBe('Link');
+ });
});
- it('renders group description', () => {
- expect(findGroupDescription().text()).toBe(mockGroup1.description);
+ describe('on Link button click', () => {
+ let addSubscriptionSpy;
+
+ beforeEach(() => {
+ createComponent({ mountFn: mount });
+
+ addSubscriptionSpy = jest.spyOn(JiraConnectApi, 'addSubscription').mockResolvedValue();
+ });
+
+ it('sets button to loading and sends request', async () => {
+ expect(findLinkButton().props('loading')).toBe(false);
+
+ clickLinkButton();
+
+ await wrapper.vm.$nextTick();
+
+ expect(findLinkButton().props('loading')).toBe(true);
+
+ expect(addSubscriptionSpy).toHaveBeenCalledWith(mockSubscriptionPath, mockGroup1.full_path);
+ });
+
+ describe('when request is successful', () => {
+ it('reloads the page', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('when request has errors', () => {
+ const mockErrorMessage = 'error message';
+ const mockError = { response: { data: { error: mockErrorMessage } } };
+
+ beforeEach(() => {
+ addSubscriptionSpy = jest
+ .spyOn(JiraConnectApi, 'addSubscription')
+ .mockRejectedValue(mockError);
+ });
+
+ it('emits `error` event', async () => {
+ clickLinkButton();
+
+ await waitForPromises();
+
+ expect(reloadSpy).not.toHaveBeenCalled();
+ expect(wrapper.emitted('error')[0][0]).toBe(mockErrorMessage);
+ });
+ });
});
});
diff --git a/spec/frontend/jira_connect/components/groups_list_spec.js b/spec/frontend/jira_connect/components/groups_list_spec.js
index 94f158e6344..5c645eccc0e 100644
--- a/spec/frontend/jira_connect/components/groups_list_spec.js
+++ b/spec/frontend/jira_connect/components/groups_list_spec.js
@@ -1,5 +1,5 @@
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlLoadingIcon } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import { fetchGroups } from '~/jira_connect/api';
@@ -28,6 +28,7 @@ describe('GroupsList', () => {
wrapper = null;
});
+ const findGlAlert = () => wrapper.find(GlAlert);
const findGlLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findAllItems = () => wrapper.findAll(GroupsListItem);
const findFirstItem = () => findAllItems().at(0);
@@ -45,6 +46,18 @@ describe('GroupsList', () => {
});
});
+ describe('error fetching groups', () => {
+ it('renders error message', async () => {
+ fetchGroups.mockRejectedValue();
+ createComponent();
+
+ await waitForPromises();
+
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toBe('Failed to load namespaces. Please try again.');
+ });
+ });
+
describe('no groups returned', () => {
it('renders empty state', async () => {
fetchGroups.mockResolvedValue(mockEmptyResponse);
@@ -57,15 +70,28 @@ describe('GroupsList', () => {
});
describe('with groups returned', () => {
- it('renders groups list', async () => {
+ beforeEach(async () => {
fetchGroups.mockResolvedValue({ data: [mockGroup1, mockGroup2] });
createComponent();
await waitForPromises();
+ });
+ it('renders groups list', () => {
expect(findAllItems().length).toBe(2);
expect(findFirstItem().props('group')).toBe(mockGroup1);
expect(findSecondItem().props('group')).toBe(mockGroup2);
});
+
+ it('shows error message on $emit from item', async () => {
+ const errorMessage = 'error message';
+
+ findFirstItem().vm.$emit('error', errorMessage);
+
+ await wrapper.vm.$nextTick();
+
+ expect(findGlAlert().exists()).toBe(true);
+ expect(findGlAlert().text()).toContain(errorMessage);
+ });
});
});
diff --git a/spec/frontend/jira_connect/index_spec.js b/spec/frontend/jira_connect/index_spec.js
new file mode 100644
index 00000000000..eb54fe6476f
--- /dev/null
+++ b/spec/frontend/jira_connect/index_spec.js
@@ -0,0 +1,56 @@
+import waitForPromises from 'helpers/wait_for_promises';
+import { initJiraConnect } from '~/jira_connect';
+import { removeSubscription } from '~/jira_connect/api';
+
+jest.mock('~/jira_connect/api', () => ({
+ removeSubscription: jest.fn().mockResolvedValue(),
+ getLocation: jest.fn().mockResolvedValue('test/location'),
+}));
+
+describe('initJiraConnect', () => {
+ window.AP = {
+ navigator: {
+ reload: jest.fn(),
+ },
+ };
+
+ beforeEach(async () => {
+ 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 href="https://gitlab.com/sub1" class="js-jira-connect-remove-subscription">Remove</a>
+ <a href="https://gitlab.com/sub2" class="js-jira-connect-remove-subscription">Remove</a>
+ <a href="https://gitlab.com/sub3" class="js-jira-connect-remove-subscription">Remove</a>
+ `);
+
+ await initJiraConnect();
+ });
+
+ 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');
+ });
+ });
+ });
+
+ describe('`remove subscription` buttons', () => {
+ describe('on click', () => {
+ it('calls `removeSubscription`', () => {
+ Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach(
+ (removeSubscriptionButton) => {
+ removeSubscriptionButton.dispatchEvent(new Event('click'));
+
+ waitForPromises();
+
+ expect(removeSubscription).toHaveBeenCalledWith(removeSubscriptionButton.href);
+ expect(removeSubscription).toHaveBeenCalledTimes(1);
+
+ removeSubscription.mockClear();
+ },
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/mock_data.js b/spec/frontend/jira_connect/mock_data.js
index 31565912489..22255fabc3d 100644
--- a/spec/frontend/jira_connect/mock_data.js
+++ b/spec/frontend/jira_connect/mock_data.js
@@ -3,6 +3,7 @@ export const mockGroup1 = {
avatar_url: 'avatar.png',
name: 'Gitlab Org',
full_name: 'Gitlab Org',
+ full_path: 'gitlab-org',
description: 'Open source software to collaborate on code',
};
@@ -11,5 +12,6 @@ export const mockGroup2 = {
avatar_url: 'avatar.png',
name: 'Gitlab Com',
full_name: 'Gitlab Com',
+ full_path: 'gitlab-com',
description: 'For GitLab company related projects',
};