diff options
Diffstat (limited to 'spec/javascripts/ide')
14 files changed, 754 insertions, 169 deletions
diff --git a/spec/javascripts/ide/components/branches/item_spec.js b/spec/javascripts/ide/components/branches/item_spec.js new file mode 100644 index 00000000000..8b756c8f168 --- /dev/null +++ b/spec/javascripts/ide/components/branches/item_spec.js @@ -0,0 +1,53 @@ +import Vue from 'vue'; +import mountCompontent from 'spec/helpers/vue_mount_component_helper'; +import router from '~/ide/ide_router'; +import Item from '~/ide/components/branches/item.vue'; +import { getTimeago } from '~/lib/utils/datetime_utility'; +import { projectData } from '../../mock_data'; + +const TEST_BRANCH = { + name: 'master', + committedDate: '2018-01-05T05:50Z', +}; +const TEST_PROJECT_ID = projectData.name_with_namespace; + +describe('IDE branch item', () => { + const Component = Vue.extend(Item); + let vm; + + beforeEach(() => { + vm = mountCompontent(Component, { + item: { ...TEST_BRANCH }, + projectId: TEST_PROJECT_ID, + isActive: false, + }); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders branch name and timeago', () => { + const timeText = getTimeago().format(TEST_BRANCH.committedDate); + expect(vm.$el).toContainText(TEST_BRANCH.name); + expect(vm.$el.querySelector('time')).toHaveText(timeText); + expect(vm.$el.querySelector('.ic-mobile-issue-close')).toBe(null); + }); + + it('renders link to branch', () => { + const expectedHref = router.resolve(`/project/${TEST_PROJECT_ID}/edit/${TEST_BRANCH.name}`).href; + expect(vm.$el).toMatch('a'); + expect(vm.$el).toHaveAttr('href', expectedHref); + }); + + it('renders icon if isActive', done => { + vm.isActive = true; + + vm.$nextTick() + .then(() => { + expect(vm.$el.querySelector('.ic-mobile-issue-close')).not.toBe(null); + }) + .then(done) + .catch(done.fail); + }); +}); diff --git a/spec/javascripts/ide/components/branches/search_list_spec.js b/spec/javascripts/ide/components/branches/search_list_spec.js new file mode 100644 index 00000000000..c3f84ba1c24 --- /dev/null +++ b/spec/javascripts/ide/components/branches/search_list_spec.js @@ -0,0 +1,79 @@ +import Vue from 'vue'; +import store from '~/ide/stores'; +import * as types from '~/ide/stores/modules/branches/mutation_types'; +import List from '~/ide/components/branches/search_list.vue'; +import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper'; +import { branches as testBranches } from '../../mock_data'; +import { resetStore } from '../../helpers'; + +describe('IDE branches search list', () => { + const Component = Vue.extend(List); + let vm; + + beforeEach(() => { + vm = createComponentWithStore(Component, store, {}); + + spyOn(vm, 'fetchBranches'); + + vm.$mount(); + }); + + afterEach(() => { + vm.$destroy(); + + resetStore(store); + }); + + it('calls fetch on mounted', () => { + expect(vm.fetchBranches).toHaveBeenCalledWith({ + search: '', + }); + }); + + it('renders loading icon', done => { + vm.$store.state.branches.isLoading = true; + + vm.$nextTick() + .then(() => { + expect(vm.$el).toContainElement('.loading-container'); + }) + .then(done) + .catch(done.fail); + }); + + it('renders branches not found when search is not empty', done => { + vm.search = 'testing'; + + vm.$nextTick(() => { + expect(vm.$el).toContainText('No branches found'); + + done(); + }); + }); + + describe('with branches', () => { + const currentBranch = testBranches[1]; + + beforeEach(done => { + vm.$store.state.currentBranchId = currentBranch.name; + vm.$store.commit(`branches/${types.RECEIVE_BRANCHES_SUCCESS}`, testBranches); + + vm.$nextTick(done); + }); + + it('renders list', () => { + const elementText = Array.from(vm.$el.querySelectorAll('li strong')) + .map(x => x.textContent.trim()); + + expect(elementText).toEqual(testBranches.map(x => x.name)); + }); + + it('renders check next to active branch', () => { + const checkedText = Array.from(vm.$el.querySelectorAll('li')) + .filter(x => x.querySelector('.ide-search-list-current-icon svg')) + .map(x => x.querySelector('strong').textContent.trim()); + + expect(checkedText).toEqual([currentBranch.name]); + }); + }); +}); diff --git a/spec/javascripts/ide/components/merge_requests/dropdown_spec.js b/spec/javascripts/ide/components/merge_requests/dropdown_spec.js deleted file mode 100644 index 74884c9a362..00000000000 --- a/spec/javascripts/ide/components/merge_requests/dropdown_spec.js +++ /dev/null @@ -1,47 +0,0 @@ -import Vue from 'vue'; -import { createStore } from '~/ide/stores'; -import Dropdown from '~/ide/components/merge_requests/dropdown.vue'; -import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper'; -import { mergeRequests } from '../../mock_data'; - -describe('IDE merge requests dropdown', () => { - const Component = Vue.extend(Dropdown); - let vm; - - beforeEach(() => { - const store = createStore(); - - vm = createComponentWithStore(Component, store, { show: false }).$mount(); - }); - - afterEach(() => { - vm.$destroy(); - }); - - it('does not render tabs when show is false', () => { - expect(vm.$el.querySelector('.nav-links')).toBe(null); - }); - - describe('when show is true', () => { - beforeEach(done => { - vm.show = true; - vm.$store.state.mergeRequests.assigned.mergeRequests.push(mergeRequests[0]); - - vm.$nextTick(done); - }); - - it('renders tabs', () => { - expect(vm.$el.querySelector('.nav-links')).not.toBe(null); - }); - - it('renders count for assigned & created data', () => { - expect(vm.$el.querySelector('.nav-links a').textContent).toContain('Created by me'); - expect(vm.$el.querySelector('.nav-links a .badge').textContent).toContain('0'); - - expect(vm.$el.querySelectorAll('.nav-links a')[1].textContent).toContain('Assigned to me'); - expect( - vm.$el.querySelectorAll('.nav-links a')[1].querySelector('.badge').textContent, - ).toContain('1'); - }); - }); -}); diff --git a/spec/javascripts/ide/components/merge_requests/item_spec.js b/spec/javascripts/ide/components/merge_requests/item_spec.js index 51c4cddef2f..750948cae3c 100644 --- a/spec/javascripts/ide/components/merge_requests/item_spec.js +++ b/spec/javascripts/ide/components/merge_requests/item_spec.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +import router from '~/ide/ide_router'; import Item from '~/ide/components/merge_requests/item.vue'; import mountCompontent from '../../../helpers/vue_mount_component_helper'; @@ -27,6 +28,12 @@ describe('IDE merge request item', () => { expect(vm.$el.textContent).toContain('gitlab-org/gitlab-ce!1'); }); + it('renders link with href', () => { + const expectedHref = router.resolve(`/project/${vm.item.projectPathWithNamespace}/merge_requests/${vm.item.iid}`).href; + expect(vm.$el).toMatch('a'); + expect(vm.$el).toHaveAttr('href', expectedHref); + }); + it('renders icon if ID matches currentId', () => { expect(vm.$el.querySelector('.ic-mobile-issue-close')).not.toBe(null); }); @@ -50,12 +57,4 @@ describe('IDE merge request item', () => { done(); }); }); - - it('emits click event on click', () => { - spyOn(vm, '$emit'); - - vm.$el.click(); - - expect(vm.$emit).toHaveBeenCalledWith('click', vm.item); - }); }); diff --git a/spec/javascripts/ide/components/merge_requests/list_spec.js b/spec/javascripts/ide/components/merge_requests/list_spec.js index f4b393778dc..c761315444c 100644 --- a/spec/javascripts/ide/components/merge_requests/list_spec.js +++ b/spec/javascripts/ide/components/merge_requests/list_spec.js @@ -10,10 +10,7 @@ describe('IDE merge requests list', () => { let vm; beforeEach(() => { - vm = createComponentWithStore(Component, store, { - type: 'created', - emptyText: 'empty text', - }); + vm = createComponentWithStore(Component, store, {}); spyOn(vm, 'fetchMergeRequests'); @@ -28,13 +25,13 @@ describe('IDE merge requests list', () => { it('calls fetch on mounted', () => { expect(vm.fetchMergeRequests).toHaveBeenCalledWith({ - type: 'created', search: '', + type: '', }); }); it('renders loading icon', done => { - vm.$store.state.mergeRequests.created.isLoading = true; + vm.$store.state.mergeRequests.isLoading = true; vm.$nextTick(() => { expect(vm.$el.querySelector('.loading-container')).not.toBe(null); @@ -43,10 +40,6 @@ describe('IDE merge requests list', () => { }); }); - it('renders empty text when no merge requests exist', () => { - expect(vm.$el.textContent).toContain('empty text'); - }); - it('renders no search results text when search is not empty', done => { vm.search = 'testing'; @@ -57,9 +50,29 @@ describe('IDE merge requests list', () => { }); }); + it('clicking on search type, sets currentSearchType and loads merge requests', done => { + vm.onSearchFocus(); + + vm.$nextTick() + .then(() => { + vm.$el.querySelector('li button').click(); + + return vm.$nextTick(); + }) + .then(() => { + expect(vm.currentSearchType).toEqual(vm.$options.searchTypes[0]); + expect(vm.fetchMergeRequests).toHaveBeenCalledWith({ + type: vm.currentSearchType.type, + search: '', + }); + }) + .then(done) + .catch(done.fail); + }); + describe('with merge requests', () => { beforeEach(done => { - vm.$store.state.mergeRequests.created.mergeRequests.push({ + vm.$store.state.mergeRequests.mergeRequests.push({ ...mergeRequests[0], projectPathWithNamespace: 'gitlab-org/gitlab-ce', }); @@ -71,35 +84,6 @@ describe('IDE merge requests list', () => { expect(vm.$el.querySelectorAll('li').length).toBe(1); expect(vm.$el.querySelector('li').textContent).toContain(mergeRequests[0].title); }); - - it('calls openMergeRequest when clicking merge request', done => { - spyOn(vm, 'openMergeRequest'); - vm.$el.querySelector('li button').click(); - - vm.$nextTick(() => { - expect(vm.openMergeRequest).toHaveBeenCalledWith({ - projectPath: 'gitlab-org/gitlab-ce', - id: 1, - }); - - done(); - }); - }); - }); - - describe('focusSearch', () => { - it('focuses search input when loading is false', done => { - spyOn(vm.$refs.searchInput, 'focus'); - - vm.$store.state.mergeRequests.created.isLoading = false; - vm.focusSearch(); - - vm.$nextTick(() => { - expect(vm.$refs.searchInput.focus).toHaveBeenCalled(); - - done(); - }); - }); }); describe('searchMergeRequests', () => { @@ -123,4 +107,52 @@ describe('IDE merge requests list', () => { expect(vm.loadMergeRequests).toHaveBeenCalled(); }); }); + + describe('onSearchFocus', () => { + it('shows search types', done => { + vm.$el.querySelector('input').dispatchEvent(new Event('focus')); + + expect(vm.hasSearchFocus).toBe(true); + expect(vm.showSearchTypes).toBe(true); + + vm.$nextTick() + .then(() => { + const expectedSearchTypes = vm.$options.searchTypes.map(x => x.label); + const renderedSearchTypes = Array.from(vm.$el.querySelectorAll('li')) + .map(x => x.textContent.trim()); + + expect(renderedSearchTypes).toEqual(expectedSearchTypes); + }) + .then(done) + .catch(done.fail); + }); + + it('does not show search types, if already has search value', () => { + vm.search = 'lorem ipsum'; + vm.$el.querySelector('input').dispatchEvent(new Event('focus')); + + expect(vm.hasSearchFocus).toBe(true); + expect(vm.showSearchTypes).toBe(false); + }); + + it('does not show search types, if already has a search type', () => { + vm.currentSearchType = {}; + vm.$el.querySelector('input').dispatchEvent(new Event('focus')); + + expect(vm.hasSearchFocus).toBe(true); + expect(vm.showSearchTypes).toBe(false); + }); + + it('resets hasSearchFocus when search changes', done => { + vm.hasSearchFocus = true; + vm.search = 'something else'; + + vm.$nextTick() + .then(() => { + expect(vm.hasSearchFocus).toBe(false); + }) + .then(done) + .catch(done.fail); + }); + }); }); diff --git a/spec/javascripts/ide/components/nav_dropdown_button_spec.js b/spec/javascripts/ide/components/nav_dropdown_button_spec.js new file mode 100644 index 00000000000..0a58e260280 --- /dev/null +++ b/spec/javascripts/ide/components/nav_dropdown_button_spec.js @@ -0,0 +1,63 @@ +import Vue from 'vue'; +import NavDropdownButton from '~/ide/components/nav_dropdown_button.vue'; +import store from '~/ide/stores'; +import { trimText } from 'spec/helpers/vue_component_helper'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; +import { resetStore } from '../helpers'; + +describe('NavDropdown', () => { + const TEST_BRANCH_ID = 'lorem-ipsum-dolar'; + const TEST_MR_ID = '12345'; + const Component = Vue.extend(NavDropdownButton); + let vm; + + beforeEach(() => { + vm = mountComponentWithStore(Component, { store }); + + vm.$mount(); + }); + + afterEach(() => { + vm.$destroy(); + + resetStore(store); + }); + + it('renders empty placeholders, if state is falsey', () => { + expect(trimText(vm.$el.textContent)).toEqual('- -'); + }); + + it('renders branch name, if state has currentBranchId', done => { + vm.$store.state.currentBranchId = TEST_BRANCH_ID; + + vm.$nextTick() + .then(() => { + expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} -`); + }) + .then(done) + .catch(done.fail); + }); + + it('renders mr id, if state has currentMergeRequestId', done => { + vm.$store.state.currentMergeRequestId = TEST_MR_ID; + + vm.$nextTick() + .then(() => { + expect(trimText(vm.$el.textContent)).toEqual(`- !${TEST_MR_ID}`); + }) + .then(done) + .catch(done.fail); + }); + + it('renders branch and mr, if state has both', done => { + vm.$store.state.currentBranchId = TEST_BRANCH_ID; + vm.$store.state.currentMergeRequestId = TEST_MR_ID; + + vm.$nextTick() + .then(() => { + expect(trimText(vm.$el.textContent)).toEqual(`${TEST_BRANCH_ID} !${TEST_MR_ID}`); + }) + .then(done) + .catch(done.fail); + }); +}); diff --git a/spec/javascripts/ide/components/nav_dropdown_spec.js b/spec/javascripts/ide/components/nav_dropdown_spec.js new file mode 100644 index 00000000000..af6665bcd62 --- /dev/null +++ b/spec/javascripts/ide/components/nav_dropdown_spec.js @@ -0,0 +1,50 @@ +import $ from 'jquery'; +import Vue from 'vue'; +import store from '~/ide/stores'; +import NavDropdown from '~/ide/components/nav_dropdown.vue'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; + +describe('IDE NavDropdown', () => { + const Component = Vue.extend(NavDropdown); + let vm; + let $dropdown; + + beforeEach(() => { + vm = mountComponentWithStore(Component, { store }); + $dropdown = $(vm.$el); + + // block dispatch from doing anything + spyOn(vm.$store, 'dispatch'); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders nothing initially', () => { + expect(vm.$el).not.toContainElement('.ide-nav-form'); + }); + + it('renders nav form when show.bs.dropdown', done => { + $dropdown.trigger('show.bs.dropdown'); + + vm.$nextTick() + .then(() => { + expect(vm.$el).toContainElement('.ide-nav-form'); + }) + .then(done) + .catch(done.fail); + }); + + it('destroys nav form when closed', done => { + $dropdown.trigger('show.bs.dropdown'); + $dropdown.trigger('hide.bs.dropdown'); + + vm.$nextTick() + .then(() => { + expect(vm.$el).not.toContainElement('.ide-nav-form'); + }) + .then(done) + .catch(done.fail); + }); +}); diff --git a/spec/javascripts/ide/components/shared/tokened_input_spec.js b/spec/javascripts/ide/components/shared/tokened_input_spec.js new file mode 100644 index 00000000000..09940fe8c6a --- /dev/null +++ b/spec/javascripts/ide/components/shared/tokened_input_spec.js @@ -0,0 +1,132 @@ +import Vue from 'vue'; +import TokenedInput from '~/ide/components/shared/tokened_input.vue'; +import mountComponent from 'spec/helpers/vue_mount_component_helper'; + +const TEST_PLACEHOLDER = 'Searching in test'; +const TEST_TOKENS = [ + { label: 'lorem', id: 1 }, + { label: 'ipsum', id: 2 }, + { label: 'dolar', id: 3 }, +]; +const TEST_VALUE = 'lorem'; + +function getTokenElements(vm) { + return Array.from(vm.$el.querySelectorAll('.filtered-search-token button')); +} + +function createBackspaceEvent() { + const e = new Event('keyup'); + e.keyCode = 8; + e.which = e.keyCode; + e.altKey = false; + e.ctrlKey = true; + e.shiftKey = false; + e.metaKey = false; + return e; +} + +describe('IDE shared/TokenedInput', () => { + const Component = Vue.extend(TokenedInput); + let vm; + + beforeEach(() => { + vm = mountComponent(Component, { + tokens: TEST_TOKENS, + placeholder: TEST_PLACEHOLDER, + value: TEST_VALUE, + }); + + spyOn(vm, '$emit'); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders tokens', () => { + const renderedTokens = getTokenElements(vm) + .map(x => x.textContent.trim()); + + expect(renderedTokens).toEqual(TEST_TOKENS.map(x => x.label)); + }); + + it('renders input', () => { + expect(vm.$refs.input).toBeTruthy(); + expect(vm.$refs.input).toHaveValue(TEST_VALUE); + }); + + it('renders placeholder, when tokens are empty', done => { + vm.tokens = []; + + vm.$nextTick() + .then(() => { + expect(vm.$refs.input).toHaveAttr('placeholder', TEST_PLACEHOLDER); + }) + .then(done) + .catch(done.fail); + }); + + it('triggers "removeToken" on token click', () => { + getTokenElements(vm)[0].click(); + + expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[0]); + }); + + it('when input triggers backspace event, it calls "onBackspace"', () => { + spyOn(vm, 'onBackspace'); + + vm.$refs.input.dispatchEvent(createBackspaceEvent()); + vm.$refs.input.dispatchEvent(createBackspaceEvent()); + + expect(vm.onBackspace).toHaveBeenCalledTimes(2); + }); + + it('triggers "removeToken" on backspaces when value is empty', () => { + vm.value = ''; + + vm.onBackspace(); + expect(vm.$emit).not.toHaveBeenCalled(); + expect(vm.backspaceCount).toEqual(1); + + vm.onBackspace(); + expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[TEST_TOKENS.length - 1]); + expect(vm.backspaceCount).toEqual(0); + }); + + it('does not trigger "removeToken" on backspaces when value is not empty', () => { + vm.onBackspace(); + vm.onBackspace(); + + expect(vm.backspaceCount).toEqual(0); + expect(vm.$emit).not.toHaveBeenCalled(); + }); + + it('does not trigger "removeToken" on backspaces when tokens are empty', () => { + vm.tokens = []; + + vm.onBackspace(); + vm.onBackspace(); + + expect(vm.backspaceCount).toEqual(0); + expect(vm.$emit).not.toHaveBeenCalled(); + }); + + it('triggers "focus" on input focus', () => { + vm.$refs.input.dispatchEvent(new Event('focus')); + + expect(vm.$emit).toHaveBeenCalledWith('focus'); + }); + + it('triggers "blur" on input blur', () => { + vm.$refs.input.dispatchEvent(new Event('blur')); + + expect(vm.$emit).toHaveBeenCalledWith('blur'); + }); + + it('triggers "input" with value on input change', () => { + vm.$refs.input.value = 'something-else'; + vm.$refs.input.dispatchEvent(new Event('input')); + + expect(vm.$emit).toHaveBeenCalledWith('input', 'something-else'); + }); +}); diff --git a/spec/javascripts/ide/helpers.js b/spec/javascripts/ide/helpers.js index 569fa5c7aae..c11c482fef8 100644 --- a/spec/javascripts/ide/helpers.js +++ b/spec/javascripts/ide/helpers.js @@ -4,6 +4,7 @@ import state from '~/ide/stores/state'; import commitState from '~/ide/stores/modules/commit/state'; import mergeRequestsState from '~/ide/stores/modules/merge_requests/state'; import pipelinesState from '~/ide/stores/modules/pipelines/state'; +import branchesState from '~/ide/stores/modules/branches/state'; export const resetStore = store => { const newState = { @@ -11,6 +12,7 @@ export const resetStore = store => { commit: commitState(), mergeRequests: mergeRequestsState(), pipelines: pipelinesState(), + branches: branchesState(), }; store.replaceState(newState); }; diff --git a/spec/javascripts/ide/mock_data.js b/spec/javascripts/ide/mock_data.js index 7be450a0df7..4fe826943b2 100644 --- a/spec/javascripts/ide/mock_data.js +++ b/spec/javascripts/ide/mock_data.js @@ -165,3 +165,33 @@ export const mergeRequests = [ web_url: `${gl.TEST_HOST}/namespace/project-path/merge_requests/1`, }, ]; + +export const branches = [ + { + id: 1, + name: 'master', + commit: { + message: 'Update master branch', + committed_date: '2018-08-01T00:20:05Z', + }, + can_push: true, + }, + { + id: 2, + name: 'feature/lorem-ipsum', + commit: { + message: 'Update some stuff', + committed_date: '2018-08-02T00:00:05Z', + }, + can_push: true, + }, + { + id: 3, + name: 'feature/dolar-amit', + commit: { + message: 'Update some more stuff', + committed_date: '2018-06-30T00:20:05Z', + }, + can_push: true, + }, +]; diff --git a/spec/javascripts/ide/stores/modules/branches/actions_spec.js b/spec/javascripts/ide/stores/modules/branches/actions_spec.js new file mode 100644 index 00000000000..a0fce578958 --- /dev/null +++ b/spec/javascripts/ide/stores/modules/branches/actions_spec.js @@ -0,0 +1,193 @@ +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; +import state from '~/ide/stores/modules/branches/state'; +import * as types from '~/ide/stores/modules/branches/mutation_types'; +import testAction from 'spec/helpers/vuex_action_helper'; +import { + requestBranches, + receiveBranchesError, + receiveBranchesSuccess, + fetchBranches, + resetBranches, + openBranch, +} from '~/ide/stores/modules/branches/actions'; +import { branches, projectData } from '../../../mock_data'; + +describe('IDE branches actions', () => { + const TEST_SEARCH = 'foosearch'; + let mockedContext; + let mockedState; + let mock; + + beforeEach(() => { + mockedContext = { + dispatch() {}, + rootState: { + currentProjectId: projectData.name_with_namespace, + }, + rootGetters: { + currentProject: projectData, + }, + state: state(), + }; + + // testAction looks for rootGetters in state, + // so they need to be concatenated here. + mockedState = { + ...mockedContext.state, + ...mockedContext.rootGetters, + ...mockedContext.rootState, + }; + + mock = new MockAdapter(axios); + }); + + afterEach(() => { + mock.restore(); + }); + + describe('requestBranches', () => { + it('should commit request', done => { + testAction( + requestBranches, + null, + mockedContext.state, + [{ type: types.REQUEST_BRANCHES }], + [], + done, + ); + }); + }); + + describe('receiveBranchesError', () => { + it('should should commit error', done => { + + testAction( + receiveBranchesError, + { search: TEST_SEARCH }, + mockedContext.state, + [{ type: types.RECEIVE_BRANCHES_ERROR }], + [ + { + type: 'setErrorMessage', + payload: { + text: 'Error loading branches.', + action: jasmine.any(Function), + actionText: 'Please try again', + actionPayload: { search: TEST_SEARCH }, + }, + }, + ], + done, + ); + }); + }); + + describe('receiveBranchesSuccess', () => { + it('should commit received data', done => { + testAction( + receiveBranchesSuccess, + branches, + mockedContext.state, + [{ type: types.RECEIVE_BRANCHES_SUCCESS, payload: branches }], + [], + done, + ); + }); + }); + + describe('fetchBranches', () => { + beforeEach(() => { + gon.api_version = 'v4'; + }); + + describe('success', () => { + beforeEach(() => { + mock.onGet(/\/api\/v4\/projects\/\d+\/repository\/branches(.*)$/).replyOnce(200, branches); + }); + + it('calls API with params', () => { + const apiSpy = spyOn(axios, 'get').and.callThrough(); + + fetchBranches(mockedContext, { search: TEST_SEARCH }); + + expect(apiSpy).toHaveBeenCalledWith(jasmine.anything(), { + params: jasmine.objectContaining({ + search: TEST_SEARCH, + sort: 'updated_desc', + }), + }); + }); + + it('dispatches success with received data', done => { + testAction( + fetchBranches, + { search: TEST_SEARCH }, + mockedState, + [], + [ + { type: 'requestBranches' }, + { type: 'resetBranches' }, + { + type: 'receiveBranchesSuccess', + payload: branches, + }, + ], + done, + ); + }); + }); + + describe('error', () => { + beforeEach(() => { + mock.onGet(/\/api\/v4\/projects\/\d+\/repository\/branches(.*)$/).replyOnce(500); + }); + + it('dispatches error', done => { + testAction( + fetchBranches, + { search: TEST_SEARCH }, + mockedState, + [], + [ + { type: 'requestBranches' }, + { type: 'resetBranches' }, + { + type: 'receiveBranchesError', + payload: { search: TEST_SEARCH }, + }, + ], + done, + ); + }); + }); + + describe('resetBranches', () => { + it('commits reset', done => { + testAction( + resetBranches, + null, + mockedContext.state, + [{ type: types.RESET_BRANCHES }], + [], + done, + ); + }); + }); + + describe('openBranch', () => { + it('dispatches goToRoute action with path', done => { + const branchId = branches[0].name; + const expectedPath = `/project/${projectData.name_with_namespace}/edit/${branchId}`; + testAction( + openBranch, + branchId, + mockedState, + [], + [{ type: 'goToRoute', payload: expectedPath }], + done, + ); + }); + }); + }); +}); diff --git a/spec/javascripts/ide/stores/modules/branches/mutations_spec.js b/spec/javascripts/ide/stores/modules/branches/mutations_spec.js new file mode 100644 index 00000000000..be91440f119 --- /dev/null +++ b/spec/javascripts/ide/stores/modules/branches/mutations_spec.js @@ -0,0 +1,51 @@ +import state from '~/ide/stores/modules/branches/state'; +import mutations from '~/ide/stores/modules/branches/mutations'; +import * as types from '~/ide/stores/modules/branches/mutation_types'; +import { branches } from '../../../mock_data'; + +describe('IDE branches mutations', () => { + let mockedState; + + beforeEach(() => { + mockedState = state(); + }); + + describe(types.REQUEST_BRANCHES, () => { + it('sets loading to true', () => { + mutations[types.REQUEST_BRANCHES](mockedState); + + expect(mockedState.isLoading).toBe(true); + }); + }); + + describe(types.RECEIVE_BRANCHES_ERROR, () => { + it('sets loading to false', () => { + mutations[types.RECEIVE_BRANCHES_ERROR](mockedState); + + expect(mockedState.isLoading).toBe(false); + }); + }); + + describe(types.RECEIVE_BRANCHES_SUCCESS, () => { + it('sets branches', () => { + const expectedBranches = branches.map(branch => ({ + name: branch.name, + committedDate: branch.commit.committed_date, + })); + + mutations[types.RECEIVE_BRANCHES_SUCCESS](mockedState, branches); + + expect(mockedState.branches).toEqual(expectedBranches); + }); + }); + + describe(types.RESET_BRANCHES, () => { + it('clears branches array', () => { + mockedState.branches = ['test']; + + mutations[types.RESET_BRANCHES](mockedState); + + expect(mockedState.branches).toEqual([]); + }); + }); +}); diff --git a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js index d063f1ea860..62699143a91 100644 --- a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js +++ b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js @@ -8,9 +8,7 @@ import { receiveMergeRequestsSuccess, fetchMergeRequests, resetMergeRequests, - openMergeRequest, } from '~/ide/stores/modules/merge_requests/actions'; -import router from '~/ide/ide_router'; import { mergeRequests } from '../../../mock_data'; import testAction from '../../../../helpers/vuex_action_helper'; @@ -28,12 +26,12 @@ describe('IDE merge requests actions', () => { }); describe('requestMergeRequests', () => { - it('should should commit request', done => { + it('should commit request', done => { testAction( requestMergeRequests, - 'created', + null, mockedState, - [{ type: types.REQUEST_MERGE_REQUESTS, payload: 'created' }], + [{ type: types.REQUEST_MERGE_REQUESTS }], [], done, ); @@ -46,7 +44,7 @@ describe('IDE merge requests actions', () => { receiveMergeRequestsError, { type: 'created', search: '' }, mockedState, - [{ type: types.RECEIVE_MERGE_REQUESTS_ERROR, payload: 'created' }], + [{ type: types.RECEIVE_MERGE_REQUESTS_ERROR }], [ { type: 'setErrorMessage', @@ -67,12 +65,12 @@ describe('IDE merge requests actions', () => { it('should commit received data', done => { testAction( receiveMergeRequestsSuccess, - { type: 'created', data: 'data' }, + mergeRequests, mockedState, [ { type: types.RECEIVE_MERGE_REQUESTS_SUCCESS, - payload: { type: 'created', data: 'data' }, + payload: mergeRequests, }, ], [], @@ -129,11 +127,11 @@ describe('IDE merge requests actions', () => { mockedState, [], [ - { type: 'requestMergeRequests', payload: 'created' }, - { type: 'resetMergeRequests', payload: 'created' }, + { type: 'requestMergeRequests' }, + { type: 'resetMergeRequests' }, { type: 'receiveMergeRequestsSuccess', - payload: { type: 'created', data: mergeRequests }, + payload: mergeRequests, }, ], done, @@ -149,12 +147,12 @@ describe('IDE merge requests actions', () => { it('dispatches error', done => { testAction( fetchMergeRequests, - { type: 'created' }, + { type: 'created', search: '' }, mockedState, [], [ - { type: 'requestMergeRequests', payload: 'created' }, - { type: 'resetMergeRequests', payload: 'created' }, + { type: 'requestMergeRequests' }, + { type: 'resetMergeRequests' }, { type: 'receiveMergeRequestsError', payload: { type: 'created', search: '' } }, ], done, @@ -167,59 +165,12 @@ describe('IDE merge requests actions', () => { it('commits reset', done => { testAction( resetMergeRequests, - 'created', + null, mockedState, - [{ type: types.RESET_MERGE_REQUESTS, payload: 'created' }], + [{ type: types.RESET_MERGE_REQUESTS }], [], done, ); }); }); - - describe('openMergeRequest', () => { - beforeEach(() => { - spyOn(router, 'push'); - }); - - it('commits reset mutations and actions', done => { - const commit = jasmine.createSpy(); - const dispatch = jasmine.createSpy().and.returnValue(Promise.resolve()); - openMergeRequest({ commit, dispatch }, { projectPath: 'gitlab-org/gitlab-ce', id: '1' }); - - setTimeout(() => { - expect(commit.calls.argsFor(0)).toEqual(['CLEAR_PROJECTS', null, { root: true }]); - expect(commit.calls.argsFor(1)).toEqual(['SET_CURRENT_MERGE_REQUEST', '1', { root: true }]); - expect(commit.calls.argsFor(2)).toEqual(['RESET_OPEN_FILES', null, { root: true }]); - - expect(dispatch.calls.argsFor(0)).toEqual(['setCurrentBranchId', '', { root: true }]); - expect(dispatch.calls.argsFor(1)).toEqual([ - 'pipelines/stopPipelinePolling', - null, - { root: true }, - ]); - expect(dispatch.calls.argsFor(2)).toEqual(['setRightPane', null, { root: true }]); - expect(dispatch.calls.argsFor(3)).toEqual([ - 'pipelines/resetLatestPipeline', - null, - { root: true }, - ]); - expect(dispatch.calls.argsFor(4)).toEqual([ - 'pipelines/clearEtagPoll', - null, - { root: true }, - ]); - - done(); - }); - }); - - it('pushes new route', () => { - openMergeRequest( - { commit() {}, dispatch: () => Promise.resolve() }, - { projectPath: 'gitlab-org/gitlab-ce', id: '1' }, - ); - - expect(router.push).toHaveBeenCalledWith('/project/gitlab-org/gitlab-ce/merge_requests/1'); - }); - }); }); diff --git a/spec/javascripts/ide/stores/modules/merge_requests/mutations_spec.js b/spec/javascripts/ide/stores/modules/merge_requests/mutations_spec.js index ea03131d90d..664d3914564 100644 --- a/spec/javascripts/ide/stores/modules/merge_requests/mutations_spec.js +++ b/spec/javascripts/ide/stores/modules/merge_requests/mutations_spec.js @@ -12,29 +12,26 @@ describe('IDE merge requests mutations', () => { describe(types.REQUEST_MERGE_REQUESTS, () => { it('sets loading to true', () => { - mutations[types.REQUEST_MERGE_REQUESTS](mockedState, 'created'); + mutations[types.REQUEST_MERGE_REQUESTS](mockedState); - expect(mockedState.created.isLoading).toBe(true); + expect(mockedState.isLoading).toBe(true); }); }); describe(types.RECEIVE_MERGE_REQUESTS_ERROR, () => { it('sets loading to false', () => { - mutations[types.RECEIVE_MERGE_REQUESTS_ERROR](mockedState, 'created'); + mutations[types.RECEIVE_MERGE_REQUESTS_ERROR](mockedState); - expect(mockedState.created.isLoading).toBe(false); + expect(mockedState.isLoading).toBe(false); }); }); describe(types.RECEIVE_MERGE_REQUESTS_SUCCESS, () => { it('sets merge requests', () => { gon.gitlab_url = gl.TEST_HOST; - mutations[types.RECEIVE_MERGE_REQUESTS_SUCCESS](mockedState, { - type: 'created', - data: mergeRequests, - }); + mutations[types.RECEIVE_MERGE_REQUESTS_SUCCESS](mockedState, mergeRequests); - expect(mockedState.created.mergeRequests).toEqual([ + expect(mockedState.mergeRequests).toEqual([ { id: 1, iid: 1, @@ -50,9 +47,9 @@ describe('IDE merge requests mutations', () => { it('clears merge request array', () => { mockedState.mergeRequests = ['test']; - mutations[types.RESET_MERGE_REQUESTS](mockedState, 'created'); + mutations[types.RESET_MERGE_REQUESTS](mockedState); - expect(mockedState.created.mergeRequests).toEqual([]); + expect(mockedState.mergeRequests).toEqual([]); }); }); }); |