diff options
5 files changed, 81 insertions, 49 deletions
diff --git a/app/assets/javascripts/ide/components/jobs/list.vue b/app/assets/javascripts/ide/components/jobs/list.vue index fd6bfdf86d0..bdd0364c9b9 100644 --- a/app/assets/javascripts/ide/components/jobs/list.vue +++ b/app/assets/javascripts/ide/components/jobs/list.vue @@ -1,4 +1,5 @@ <script> +import { mapActions } from 'vuex'; import LoadingIcon from '../../../vue_shared/components/loading_icon.vue'; import Stage from './stage.vue'; @@ -17,6 +18,9 @@ export default { required: true, }, }, + methods: { + ...mapActions('pipelines', ['fetchJobs', 'toggleStageCollapsed']), + }, }; </script> @@ -32,6 +36,8 @@ export default { v-for="stage in stages" :key="stage.id" :stage="stage" + @fetch="fetchJobs" + @toggleCollapsed="toggleStageCollapsed" /> </template> </div> diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue index 370bb61bae8..5b24bb1f5a7 100644 --- a/app/assets/javascripts/ide/components/jobs/stage.vue +++ b/app/assets/javascripts/ide/components/jobs/stage.vue @@ -1,5 +1,4 @@ <script> -import { mapActions } from 'vuex'; import tooltip from '../../../vue_shared/directives/tooltip'; import Icon from '../../../vue_shared/components/icon.vue'; import CiIcon from '../../../vue_shared/components/ci_icon.vue'; @@ -38,16 +37,17 @@ export default { return this.stage.jobs.length; }, }, - created() { - this.fetchJobs(this.stage); - }, mounted() { const { stageTitle } = this.$refs; this.showTooltip = stageTitle.scrollWidth > stageTitle.offsetWidth; + + this.$emit('fetch', this.stage); }, methods: { - ...mapActions('pipelines', ['fetchJobs', 'toggleStageCollapsed']), + toggleCollapsed() { + this.$emit('toggleCollapsed', this.stage.id); + }, }, }; </script> @@ -61,7 +61,7 @@ export default { :class="{ 'border-bottom-0': stage.isCollapsed }" - @click="toggleStageCollapsed(stage.id)" + @click="toggleCollapsed" > <ci-icon :status="stage.status" diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js index 38459dfbe77..3c50279642b 100644 --- a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js +++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js @@ -39,20 +39,28 @@ export default { } }, [types.REQUEST_JOBS](state, id) { - const stage = state.stages.find(s => s.id === id); - stage.isLoading = true; + state.stages = state.stages.map(stage => ({ + ...stage, + isLoading: stage.id === id ? true : stage.isLoading, + })); }, [types.RECEIVE_JOBS_ERROR](state, id) { - const stage = state.stages.find(s => s.id === id); - stage.isLoading = false; + state.stages = state.stages.map(stage => ({ + ...stage, + isLoading: stage.id === id ? false : stage.isLoading, + })); }, [types.RECEIVE_JOBS_SUCCESS](state, { id, data }) { - const stage = state.stages.find(s => s.id === id); - stage.isLoading = false; - stage.jobs = data.latest_statuses.map(normalizeJob); + state.stages = state.stages.map(stage => ({ + ...stage, + isLoading: stage.id === id ? false : stage.isLoading, + jobs: data.latest_statuses.map(normalizeJob), + })); }, [types.TOGGLE_STAGE_COLLAPSE](state, id) { - const stage = state.stages.find(s => s.id === id); - stage.isCollapsed = !stage.isCollapsed; + state.stages = state.stages.map(stage => ({ + ...stage, + isCollapsed: stage.id === id ? !stage.isCollapsed : stage.isCollapsed, + })); }, }; diff --git a/spec/javascripts/ide/components/jobs/list_spec.js b/spec/javascripts/ide/components/jobs/list_spec.js index 484cab3c135..b24853c56fa 100644 --- a/spec/javascripts/ide/components/jobs/list_spec.js +++ b/spec/javascripts/ide/components/jobs/list_spec.js @@ -21,7 +21,12 @@ describe('IDE stages list', () => { isCollapsed: false, })), loading: false, - }).$mount(); + }); + + spyOn(vm, 'fetchJobs'); + spyOn(vm, 'toggleStageCollapsed'); + + vm.$mount(); }); afterEach(() => { @@ -42,4 +47,21 @@ describe('IDE stages list', () => { done(); }); }); + + it('calls toggleStageCollapsed when clicking stage header', done => { + vm.$el.querySelector('.card-header').click(); + + vm.$nextTick(() => { + expect(vm.toggleStageCollapsed).toHaveBeenCalledWith(0); + + done(); + }); + }); + + it('calls fetchJobs when stage is mounted', () => { + expect(vm.fetchJobs.calls.count()).toBe(stages.length); + + expect(vm.fetchJobs.calls.argsFor(0)).toEqual([vm.stages[0]]); + expect(vm.fetchJobs.calls.argsFor(1)).toEqual([vm.stages[1]]); + }); }); diff --git a/spec/javascripts/ide/components/jobs/stage_spec.js b/spec/javascripts/ide/components/jobs/stage_spec.js index 5496c57bbb7..fc3831f2d05 100644 --- a/spec/javascripts/ide/components/jobs/stage_spec.js +++ b/spec/javascripts/ide/components/jobs/stage_spec.js @@ -1,51 +1,37 @@ import Vue from 'vue'; -import MockAdapter from 'axios-mock-adapter'; -import axios from '~/lib/utils/axios_utils'; -import { createStore } from '~/ide/stores'; import Stage from '~/ide/components/jobs/stage.vue'; -import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper'; import { stages, jobs } from '../../mock_data'; describe('IDE pipeline stage', () => { const Component = Vue.extend(Stage); let vm; - let mock; let stage; - beforeEach(done => { - const store = createStore(); - mock = new MockAdapter(axios); - - Vue.set( - store.state.pipelines, - 'stages', - stages.map((mappedState, i) => ({ - ...mappedState, - id: i, - dropdownPath: mappedState.dropdown_path, - jobs: [], - isLoading: false, - isCollapsed: false, - })), - ); - - stage = store.state.pipelines.stages[0]; - - mock.onGet(stage.dropdownPath).reply(200, { - latest_statuses: jobs, + beforeEach(() => { + stage = { + ...stages[0], + id: 0, + dropdownPath: stages[0].dropdown_path, + jobs: [...jobs], + isLoading: false, + isCollapsed: false, + }; + + vm = new Component({ + propsData: { stage }, }); - vm = createComponentWithStore(Component, store, { - stage, - }).$mount(); + spyOn(vm, '$emit'); - setTimeout(done, 500); + vm.$mount(); }); afterEach(() => { vm.$destroy(); + }); - mock.restore(); + it('emits fetch event when mounted', () => { + expect(vm.$emit).toHaveBeenCalledWith('fetch', vm.stage); }); it('renders stages details', () => { @@ -57,10 +43,20 @@ describe('IDE pipeline stage', () => { }); describe('collapsed', () => { - it('toggles collapse status when clicking header', done => { + it('emits event when clicking header', done => { vm.$el.querySelector('.card-header').click(); vm.$nextTick(() => { + expect(vm.$emit).toHaveBeenCalledWith('toggleCollapsed', vm.stage.id); + + done(); + }); + }); + + it('toggles collapse status when collapsed', done => { + vm.stage.isCollapsed = true; + + vm.$nextTick(() => { expect(vm.$el.querySelector('.card-body').style.display).toBe('none'); done(); @@ -68,7 +64,7 @@ describe('IDE pipeline stage', () => { }); it('sets border bottom class when collapsed', done => { - vm.$el.querySelector('.card-header').click(); + vm.stage.isCollapsed = true; vm.$nextTick(() => { expect(vm.$el.querySelector('.card-header').classList).toContain('border-bottom-0'); |