From 00a8c64ffd18e74df4b1cdeda7776b5221fddafe Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 15 Apr 2020 06:09:49 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- spec/frontend/monitoring/mock_data.js | 12 +- .../commits/components/author_select_spec.js | 216 +++++++++++++++++++++ .../projects/commits/store/actions_spec.js | 69 +++++++ .../projects/commits/store/mutations_spec.js | 43 ++++ 4 files changed, 334 insertions(+), 6 deletions(-) create mode 100644 spec/frontend/projects/commits/components/author_select_spec.js create mode 100644 spec/frontend/projects/commits/store/actions_spec.js create mode 100644 spec/frontend/projects/commits/store/mutations_spec.js (limited to 'spec/frontend') diff --git a/spec/frontend/monitoring/mock_data.js b/spec/frontend/monitoring/mock_data.js index c9f2b110147..84dd0b70e71 100644 --- a/spec/frontend/monitoring/mock_data.js +++ b/spec/frontend/monitoring/mock_data.js @@ -213,23 +213,23 @@ export const deploymentData = [ export const annotationsData = [ { id: 'gid://gitlab/Metrics::Dashboard::Annotation/1', - from: '2020-04-01T12:51:58.373Z', - to: null, + starting_at: '2020-04-01T12:51:58.373Z', + ending_at: null, panelId: null, description: 'This is a test annotation', }, { id: 'gid://gitlab/Metrics::Dashboard::Annotation/2', description: 'test annotation 2', - from: '2020-04-02T12:51:58.373Z', - to: null, + starting_at: '2020-04-02T12:51:58.373Z', + ending_at: null, panelId: null, }, { id: 'gid://gitlab/Metrics::Dashboard::Annotation/3', description: 'test annotation 3', - from: '2020-04-04T12:51:58.373Z', - to: null, + starting_at: '2020-04-04T12:51:58.373Z', + ending_at: null, panelId: null, }, ]; diff --git a/spec/frontend/projects/commits/components/author_select_spec.js b/spec/frontend/projects/commits/components/author_select_spec.js new file mode 100644 index 00000000000..dab91d8b37c --- /dev/null +++ b/spec/frontend/projects/commits/components/author_select_spec.js @@ -0,0 +1,216 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import * as urlUtility from '~/lib/utils/url_utility'; +import AuthorSelect from '~/projects/commits/components/author_select.vue'; +import { createStore } from '~/projects/commits/store'; +import { + GlNewDropdown, + GlNewDropdownHeader, + GlSearchBoxByType, + GlNewDropdownItem, +} from '@gitlab/ui'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +const commitsPath = 'author/search/url'; +const currentAuthor = 'lorem'; +const authors = [ + { + id: 1, + name: currentAuthor, + username: 'ipsum', + avatar_url: 'some/url', + }, + { + id: 2, + name: 'lorem2', + username: 'ipsum2', + avatar_url: 'some/url/2', + }, +]; + +describe('Author Select', () => { + let store; + let wrapper; + + const createComponent = () => { + setFixtures(` +
+ +
+
+ `); + + wrapper = shallowMount(AuthorSelect, { + localVue, + store: new Vuex.Store(store), + propsData: { + projectCommitsEl: document.querySelector('.js-project-commits-show'), + }, + }); + }; + + beforeEach(() => { + store = createStore(); + store.actions.fetchAuthors = jest.fn(); + + createComponent(); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + const findDropdownContainer = () => wrapper.find({ ref: 'dropdownContainer' }); + const findDropdown = () => wrapper.find(GlNewDropdown); + const findDropdownHeader = () => wrapper.find(GlNewDropdownHeader); + const findSearchBox = () => wrapper.find(GlSearchBoxByType); + const findDropdownItems = () => wrapper.findAll(GlNewDropdownItem); + + describe('user is searching via "filter by commit message"', () => { + it('disables dropdown container', () => { + wrapper.setData({ hasSearchParam: true }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDropdownContainer().attributes('disabled')).toBeFalsy(); + }); + }); + + it('has correct tooltip message', () => { + wrapper.setData({ hasSearchParam: true }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDropdownContainer().attributes('title')).toBe( + 'Searching by both author and message is currently not supported.', + ); + }); + }); + + it('disables dropdown', () => { + wrapper.setData({ hasSearchParam: false }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDropdown().attributes('disabled')).toBeFalsy(); + }); + }); + + it('hasSearchParam if user types a truthy string', () => { + wrapper.vm.setSearchParam('false'); + + expect(wrapper.vm.hasSearchParam).toBeTruthy(); + }); + }); + + describe('dropdown', () => { + it('displays correct default text', () => { + expect(findDropdown().attributes('text')).toBe('Author'); + }); + + it('displays the current selected author', () => { + wrapper.setData({ currentAuthor }); + + return wrapper.vm.$nextTick().then(() => { + expect(findDropdown().attributes('text')).toBe(currentAuthor); + }); + }); + + it('displays correct header text', () => { + expect(findDropdownHeader().text()).toBe('Search by author'); + }); + + it('does not have popover text by default', () => { + expect(wrapper.attributes('title')).not.toExist(); + }); + }); + + describe('dropdown search box', () => { + it('has correct placeholder', () => { + expect(findSearchBox().attributes('placeholder')).toBe('Search'); + }); + + it('fetch authors on input change', () => { + const authorName = 'lorem'; + findSearchBox().vm.$emit('input', authorName); + + expect(store.actions.fetchAuthors).toHaveBeenCalledWith( + expect.anything(), + authorName, + undefined, + ); + }); + }); + + describe('dropdown list', () => { + beforeEach(() => { + store.state.commitsAuthors = authors; + store.state.commitsPath = commitsPath; + }); + + it('has a "Any Author" as the first list item', () => { + expect( + findDropdownItems() + .at(0) + .text(), + ).toBe('Any Author'); + }); + + it('displays the project authors', () => { + return wrapper.vm.$nextTick().then(() => { + expect(findDropdownItems()).toHaveLength(authors.length + 1); + }); + }); + + it('has the correct props', () => { + const [{ avatar_url, username }] = authors; + const result = { + avatarUrl: avatar_url, + secondaryText: username, + isChecked: true, + }; + + wrapper.setData({ currentAuthor }); + + return wrapper.vm.$nextTick().then(() => { + expect( + findDropdownItems() + .at(1) + .props(), + ).toEqual(expect.objectContaining(result)); + }); + }); + + it("display the author's name", () => { + return wrapper.vm.$nextTick().then(() => { + expect( + findDropdownItems() + .at(1) + .text(), + ).toBe(currentAuthor); + }); + }); + + it('passes selected author to redirectPath', () => { + const redirectToUrl = `${commitsPath}?author=${currentAuthor}`; + const spy = jest.spyOn(urlUtility, 'redirectTo'); + spy.mockImplementation(() => 'mock'); + + findDropdownItems() + .at(1) + .vm.$emit('click'); + + expect(spy).toHaveBeenCalledWith(redirectToUrl); + }); + + it('does not pass any author to redirectPath', () => { + const redirectToUrl = commitsPath; + const spy = jest.spyOn(urlUtility, 'redirectTo'); + spy.mockImplementation(); + + findDropdownItems() + .at(0) + .vm.$emit('click'); + expect(spy).toHaveBeenCalledWith(redirectToUrl); + }); + }); +}); diff --git a/spec/frontend/projects/commits/store/actions_spec.js b/spec/frontend/projects/commits/store/actions_spec.js new file mode 100644 index 00000000000..c9945e1cc27 --- /dev/null +++ b/spec/frontend/projects/commits/store/actions_spec.js @@ -0,0 +1,69 @@ +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; +import * as types from '~/projects/commits/store/mutation_types'; +import testAction from 'helpers/vuex_action_helper'; +import actions from '~/projects/commits/store/actions'; +import createState from '~/projects/commits/store/state'; +import createFlash from '~/flash'; + +jest.mock('~/flash'); + +describe('Project commits actions', () => { + let state; + let mock; + + beforeEach(() => { + state = createState(); + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('setInitialData', () => { + it(`commits ${types.SET_INITIAL_DATA}`, () => + testAction(actions.setInitialData, undefined, state, [{ type: types.SET_INITIAL_DATA }])); + }); + + describe('receiveAuthorsSuccess', () => { + it(`commits ${types.COMMITS_AUTHORS}`, () => + testAction(actions.receiveAuthorsSuccess, undefined, state, [ + { type: types.COMMITS_AUTHORS }, + ])); + }); + + describe('shows a flash message when there is an error', () => { + it('creates a flash', () => { + const mockDispatchContext = { dispatch: () => {}, commit: () => {}, state }; + actions.receiveAuthorsError(mockDispatchContext); + + expect(createFlash).toHaveBeenCalledTimes(1); + expect(createFlash).toHaveBeenCalledWith('An error occurred fetching the project authors.'); + }); + }); + + describe('fetchAuthors', () => { + it('dispatches request/receive', () => { + const path = '/autocomplete/users.json'; + state.projectId = '8'; + const data = [{ id: 1 }]; + + mock.onGet(path).replyOnce(200, data); + testAction( + actions.fetchAuthors, + null, + state, + [], + [{ type: 'receiveAuthorsSuccess', payload: data }], + ); + }); + + it('dispatches request/receive on error', () => { + const path = '/autocomplete/users.json'; + mock.onGet(path).replyOnce(500); + + testAction(actions.fetchAuthors, null, state, [], [{ type: 'receiveAuthorsError' }]); + }); + }); +}); diff --git a/spec/frontend/projects/commits/store/mutations_spec.js b/spec/frontend/projects/commits/store/mutations_spec.js new file mode 100644 index 00000000000..4fc346beb33 --- /dev/null +++ b/spec/frontend/projects/commits/store/mutations_spec.js @@ -0,0 +1,43 @@ +import * as types from '~/projects/commits/store/mutation_types'; +import mutations from '~/projects/commits/store/mutations'; +import createState from '~/projects/commits/store/state'; + +describe('Project commits mutations', () => { + let state; + + beforeEach(() => { + state = createState(); + }); + + afterEach(() => { + state = null; + }); + + describe(`${types.SET_INITIAL_DATA}`, () => { + it('sets initial data', () => { + state.commitsPath = null; + state.projectId = null; + state.commitsAuthors = []; + + const data = { + commitsPath: 'some/path', + projectId: '8', + }; + + mutations[types.SET_INITIAL_DATA](state, data); + + expect(state).toEqual(expect.objectContaining(data)); + }); + }); + + describe(`${types.COMMITS_AUTHORS}`, () => { + it('sets commitsAuthors', () => { + const authors = [{ id: 1 }, { id: 2 }]; + state.commitsAuthors = []; + + mutations[types.COMMITS_AUTHORS](state, authors); + + expect(state.commitsAuthors).toEqual(authors); + }); + }); +}); -- cgit v1.2.3