changed mutation to return new array

this makes the component completly unaware of the store, instead it emits
events to the parent which knows about the store
This commit is contained in:
Phil Hughes 2018-05-30 13:31:15 +01:00
parent c9d676c106
commit 3270e14077
No known key found for this signature in database
GPG Key ID: 32245528C52E0F9F
5 changed files with 80 additions and 48 deletions

View File

@ -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>

View File

@ -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"

View File

@ -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,
}));
},
};

View File

@ -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]]);
});
});

View File

@ -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);
beforeEach(() => {
stage = {
...stages[0],
id: 0,
dropdownPath: stages[0].dropdown_path,
jobs: [...jobs],
isLoading: false,
isCollapsed: false,
};
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,
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,9 +43,19 @@ 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');
@ -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');