Commit 66bf2de8 authored by Phil Hughes's avatar Phil Hughes

added component specs

parent dd17a484
......@@ -9,7 +9,8 @@ import pipelines from './modules/pipelines';
Vue.use(Vuex);
export default new Vuex.Store({
export const createStore = () =>
new Vuex.Store({
state: state(),
actions,
mutations,
......@@ -18,4 +19,6 @@ export default new Vuex.Store({
commit: commitModule,
pipelines,
},
});
});
export default createStore();
......@@ -4,9 +4,9 @@ export const pipelineFailed = state =>
state.latestPipeline && state.latestPipeline.details.status.text === 'failed';
export const failedStages = state =>
state.stages.filter(stage => stage.status.text === 'failed').map(stage => ({
state.stages.filter(stage => stage.status.text.toLowerCase() === 'failed').map(stage => ({
...stage,
jobs: stage.jobs.filter(job => job.status.text === 'failed'),
jobs: stage.jobs.filter(job => job.status.text.toLowerCase() === 'failed'),
}));
export const failedJobsCount = state =>
......
......@@ -38,16 +38,18 @@ export default {
}
},
[types.REQUEST_JOBS](state, id) {
state.stages = state.stages.map(stage => ({
...stage,
state.stages = state.stages.map(stage =>
Object.assign(stage, {
isLoading: id === stage.id ? true : stage.isLoading,
}));
}),
);
},
[types.RECEIVE_JOBS_ERROR](state, id) {
state.stages = state.stages.map(stage => ({
...stage,
state.stages = state.stages.map(stage =>
Object.assign(stage, {
isLoading: id === stage.id ? true : stage.isLoading,
}));
}),
);
},
[types.RECEIVE_JOBS_SUCCESS](state, { id, data }) {
const normalizeData = job => ({
......@@ -57,16 +59,18 @@ export default {
path: job.build_path,
});
state.stages = state.stages.map(stage => ({
...stage,
state.stages = state.stages.map(stage =>
Object.assign(stage, {
isLoading: id === stage.id ? false : stage.isLoading,
jobs: id === stage.id ? data.latest_statuses.map(normalizeData) : stage.jobs,
}));
}),
);
},
[types.TOGGLE_STAGE_COLLAPSE](state, id) {
state.stages = state.stages.map(stage => ({
...stage,
state.stages = state.stages.map(stage =>
Object.assign(stage, {
isCollapsed: stage.id === id ? !stage.isCollapsed : stage.isCollapsed,
}));
}),
);
},
};
......@@ -24,4 +24,5 @@ export default () => ({
unusedSeal: true,
fileFindVisible: false,
rightPane: null,
links: {},
});
import Vue from 'vue';
import JobItem from '~/ide/components/jobs/item.vue';
import mountComponent from '../../../helpers/vue_mount_component_helper';
import { jobs } from '../../mock_data';
describe('IDE jobs item', () => {
const Component = Vue.extend(JobItem);
const job = jobs[0];
let vm;
beforeEach(() => {
vm = mountComponent(Component, {
job,
});
});
afterEach(() => {
vm.$destroy();
});
it('renders job details', () => {
expect(vm.$el.textContent).toContain(job.name);
expect(vm.$el.textContent).toContain(`#${job.id}`);
});
it('renders CI icon', () => {
expect(vm.$el.querySelector('.ic-status_passed_borderless')).not.toBe(null);
});
});
import Vue from 'vue';
import StageList from '~/ide/components/jobs/list.vue';
import { createStore } from '~/ide/stores';
import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
import { stages, jobs } from '../../mock_data';
describe('IDE stages list', () => {
const Component = Vue.extend(StageList);
let vm;
beforeEach(() => {
const store = createStore();
vm = createComponentWithStore(Component, store, {
stages: stages.map((mappedState, i) => ({
...mappedState,
id: i,
dropdownPath: mappedState.dropdown_path,
jobs: [...jobs],
isLoading: false,
isCollapsed: false,
})),
loading: false,
}).$mount();
});
afterEach(() => {
vm.$destroy();
});
it('renders list of stages', () => {
expect(vm.$el.querySelectorAll('.card').length).toBe(2);
});
it('renders loading icon when no stages & is loading', done => {
vm.stages = [];
vm.loading = true;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
done();
});
});
});
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);
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 = createComponentWithStore(Component, store, {
stage,
}).$mount();
setTimeout(done);
});
afterEach(() => {
vm.$destroy();
mock.restore();
});
it('renders stages details', () => {
expect(vm.$el.textContent).toContain(vm.stage.name);
});
it('renders CI icon', () => {
expect(vm.$el.querySelector('.ic-status_failed')).not.toBe(null);
});
describe('collapsed', () => {
it('toggles collapse status when clicking header', done => {
vm.$el.querySelector('.card-header').click();
vm.$nextTick(() => {
expect(vm.$el.querySelector('.card-body').style.display).toBe('none');
done();
});
});
it('sets border bottom class when collapsed', done => {
vm.$el.querySelector('.card-header').click();
vm.$nextTick(() => {
expect(vm.$el.querySelector('.card-header').classList).toContain('border-bottom-0');
done();
});
});
});
it('renders jobs count', () => {
expect(vm.$el.querySelector('.badge').textContent).toContain('4');
});
it('renders loading icon when no jobs and isLoading is true', done => {
vm.stage.isLoading = true;
vm.stage.jobs = [];
vm.$nextTick(() => {
expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
done();
});
});
it('renders list of jobs', () => {
expect(vm.$el.querySelectorAll('.ide-job-item').length).toBe(4);
});
});
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { createStore } from '~/ide/stores';
import List from '~/ide/components/pipelines/list.vue';
import { createComponentWithStore } from '../../../helpers/vue_mount_component_helper';
import { pipelines, projectData, stages, jobs } from '../../mock_data';
describe('IDE pipelines list', () => {
const Component = Vue.extend(List);
let vm;
let mock;
beforeEach(done => {
const store = createStore();
mock = new MockAdapter(axios);
store.state.currentProjectId = 'abc/def';
store.state.currentBranchId = 'master';
store.state.projects['abc/def'] = {
...projectData,
path_with_namespace: 'abc/def',
branches: {
master: { commit: { id: '123' } },
},
};
store.state.links = { ciHelpPagePath: gl.TEST_HOST };
store.state.pipelinesEmptyStateSvgPath = gl.TEST_HOST;
store.state.pipelines.stages = stages.map((mappedState, i) => ({
...mappedState,
id: i,
dropdownPath: mappedState.dropdown_path,
jobs: [...jobs],
isLoading: false,
isCollapsed: false,
}));
mock
.onGet('/abc/def/commit/123/pipelines')
.reply(200, { pipelines: [...pipelines] }, { 'poll-interval': '-1' });
vm = createComponentWithStore(Component, store).$mount();
setTimeout(done);
});
afterEach(() => {
vm.$destroy();
mock.restore();
});
it('renders pipeline data', () => {
expect(vm.$el.textContent).toContain('#1');
});
it('renders CI icon', () => {
expect(vm.$el.querySelector('.ci-status-icon-failed')).not.toBe(null);
});
it('renders list of jobs', () => {
expect(vm.$el.querySelectorAll('.tab-pane:first-child .ide-job-item').length).toBe(
jobs.length * stages.length,
);
});
it('renders list of failed jobs on failed jobs tab', done => {
vm.$el.querySelectorAll('.tab-links a')[1].click();
vm.$nextTick(() => {
expect(vm.$el.querySelectorAll('.tab-pane.active .ide-job-item').length).toBe(2);
done();
});
});
describe('YAML error', () => {
it('renders YAML error', done => {
vm.$store.state.pipelines.latestPipeline.yamlError = 'test yaml error';
vm.$nextTick(() => {
expect(vm.$el.textContent).toContain('Found errors in your .gitlab-ci.yml:');
expect(vm.$el.textContent).toContain('test yaml error');
done();
});
});
});
describe('empty state', () => {
it('renders pipelines empty state', done => {
vm.$store.state.pipelines.latestPipeline = false;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.empty-state')).not.toBe(null);
done();
});
});
});
describe('loading state', () => {
it('renders loading state when there is no latest pipeline', done => {
vm.$store.state.pipelines.latestPipeline = null;
vm.$store.state.pipelines.isLoadingPipeline = true;
vm.$nextTick(() => {
expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
done();
});
});
});
});
import { decorateData } from '~/ide/stores/utils';
import state from '~/ide/stores/state';
import commitState from '~/ide/stores/modules/commit/state';
import pipelinesState from '~/ide/stores/modules/pipelines/state';
export const resetStore = store => {
const newState = {
...state(),
commit: commitState(),
pipelines: pipelinesState(),
};
store.replaceState(newState);
};
......
......@@ -19,26 +19,38 @@ export const pipelines = [
id: 1,
ref: 'master',
sha: '123',
status: 'failed',
details: {
status: {
icon: 'status_failed',
group: 'failed',
text: 'Failed',
},
},
commit: { id: '123' },
},
{
id: 2,
ref: 'master',
sha: '213',
status: 'success',
details: {
status: {
icon: 'status_failed',
group: 'failed',
text: 'Failed',
},
},
commit: { id: '213' },
},
];
export const stages = [
{
dropdown_path: 'testing',
dropdown_path: `${gl.TEST_HOST}/testing`,
name: 'build',
status: {
icon: 'status_failed',
group: 'failed',
text: 'Failed',
text: 'failed',
},
},
{
......@@ -47,7 +59,7 @@ export const stages = [
status: {
icon: 'status_failed',
group: 'failed',
text: 'Failed',
text: 'failed',
},
},
];
......@@ -56,28 +68,44 @@ export const jobs = [
{
id: 1,
name: 'test',
status: 'failed',
path: 'testing',
status: {
icon: 'status_passed',
text: 'passed',
},
stage: 'test',
duration: 1,
},
{
id: 2,
name: 'test 2',
status: 'failed',
path: 'testing2',
status: {
icon: 'status_passed',
text: 'passed',
},
stage: 'test',
duration: 1,
},
{
id: 3,
name: 'test 3',
status: 'failed',
path: 'testing3',
status: {
icon: 'status_passed',
text: 'passed',
},
stage: 'test',
duration: 1,
},
{
id: 4,
name: 'test 3',
status: 'failed',
name: 'test 4',
path: 'testing4',
status: {
icon: 'status_failed',
text: 'failed',
},
stage: 'build',
duration: 1,
},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment