diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-24 12:06:04 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-24 12:06:04 +0300 |
commit | bc89882970d6a14b1f72eb9c715fae90b26d066c (patch) | |
tree | f5cb59d5130d7585980eb39437071e07ebc12f87 /spec/frontend/ide | |
parent | 4a45a787703cb78c6101750cfbdc9f656b934b42 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend/ide')
3 files changed, 323 insertions, 0 deletions
diff --git a/spec/frontend/ide/components/jobs/list_spec.js b/spec/frontend/ide/components/jobs/list_spec.js new file mode 100644 index 00000000000..ec2e5b05048 --- /dev/null +++ b/spec/frontend/ide/components/jobs/list_spec.js @@ -0,0 +1,115 @@ +import { shallowMount, mount, createLocalVue } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; +import Vuex from 'vuex'; +import StageList from '~/ide/components/jobs/list.vue'; +import Stage from '~/ide/components/jobs/stage.vue'; + +const localVue = createLocalVue(); +localVue.use(Vuex); +const storeActions = { + fetchJobs: jest.fn(), + toggleStageCollapsed: jest.fn(), + setDetailJob: jest.fn(), +}; + +const store = new Vuex.Store({ + modules: { + pipelines: { + namespaced: true, + actions: storeActions, + }, + }, +}); + +describe('IDE stages list', () => { + let wrapper; + + const defaultProps = { + stages: [], + loading: false, + }; + + const stages = ['build', 'test', 'deploy'].map((name, id) => ({ + id, + name, + jobs: [], + status: { icon: 'status_success' }, + })); + + const createComponent = props => { + wrapper = shallowMount(StageList, { + propsData: { + ...defaultProps, + ...props, + }, + localVue, + store, + sync: false, + }); + }; + + afterEach(() => { + Object.values(storeActions).forEach(actionMock => actionMock.mockClear()); + }); + + afterAll(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('renders loading icon when no stages & loading', () => { + createComponent({ loading: true, stages: [] }); + + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + }); + + it('renders stages components for each stage', () => { + createComponent({ stages }); + expect(wrapper.findAll(Stage).length).toBe(stages.length); + }); + + it('triggers fetchJobs action when stage emits fetch event', () => { + createComponent({ stages }); + wrapper.find(Stage).vm.$emit('fetch'); + expect(storeActions.fetchJobs).toHaveBeenCalled(); + }); + + it('triggers toggleStageCollapsed action when stage emits toggleCollapsed event', () => { + createComponent({ stages }); + wrapper.find(Stage).vm.$emit('toggleCollapsed'); + expect(storeActions.toggleStageCollapsed).toHaveBeenCalled(); + }); + + it('triggers setDetailJob action when stage emits clickViewLog event', () => { + createComponent({ stages }); + wrapper.find(Stage).vm.$emit('clickViewLog'); + expect(storeActions.setDetailJob).toHaveBeenCalled(); + }); + + describe('integration tests', () => { + const findCardHeader = () => wrapper.find('.card-header'); + + beforeEach(() => { + wrapper = mount(StageList, { + propsData: { ...defaultProps, stages }, + store, + sync: false, + localVue, + }); + }); + + it('calls toggleStageCollapsed when clicking stage header', () => { + findCardHeader().trigger('click'); + + expect(storeActions.toggleStageCollapsed).toHaveBeenCalledWith( + expect.any(Object), + 0, + undefined, + ); + }); + + it('calls fetchJobs when stage is mounted', () => { + expect(storeActions.fetchJobs.mock.calls.map(([, stage]) => stage)).toEqual(stages); + }); + }); +}); diff --git a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap new file mode 100644 index 00000000000..5fbe6af750d --- /dev/null +++ b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`IDE pipelines list when loaded renders empty state when no latestPipeline 1`] = ` +<div + class="ide-pipeline" +> + <!----> + + <emptystate-stub + cansetci="true" + emptystatesvgpath="http://test.host" + helppagepath="http://test.host" + /> +</div> +`; diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js new file mode 100644 index 00000000000..a974139a8f9 --- /dev/null +++ b/spec/frontend/ide/components/pipelines/list_spec.js @@ -0,0 +1,193 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils'; +import Vuex from 'vuex'; +import List from '~/ide/components/pipelines/list.vue'; +import JobsList from '~/ide/components/jobs/list.vue'; +import Tab from '~/vue_shared/components/tabs/tab.vue'; +import CiIcon from '~/vue_shared/components/ci_icon.vue'; +import { GlLoadingIcon } from '@gitlab/ui'; +import { TEST_HOST } from 'helpers/test_constants'; +import { pipelines } from '../../../../javascripts/ide/mock_data'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('IDE pipelines list', () => { + let wrapper; + + const defaultState = { + links: { ciHelpPagePath: TEST_HOST }, + pipelinesEmptyStateSvgPath: TEST_HOST, + pipelines: { + stages: [], + failedStages: [], + isLoadingJobs: false, + }, + }; + + const fetchLatestPipelineMock = jest.fn(); + const failedStagesGetterMock = jest.fn().mockReturnValue([]); + + const createComponent = (state = {}) => { + const { pipelines: pipelinesState, ...restOfState } = state; + const { defaultPipelines, ...defaultRestOfState } = defaultState; + + const fakeStore = new Vuex.Store({ + getters: { currentProject: () => ({ web_url: 'some/url ' }) }, + state: { + ...defaultRestOfState, + ...restOfState, + }, + modules: { + pipelines: { + namespaced: true, + state: { + ...defaultPipelines, + ...pipelinesState, + }, + actions: { + fetchLatestPipeline: fetchLatestPipelineMock, + }, + getters: { + jobsCount: () => 1, + failedJobsCount: () => 1, + failedStages: failedStagesGetterMock, + pipelineFailed: () => false, + }, + methods: { + fetchLatestPipeline: jest.fn(), + }, + }, + }, + }); + + wrapper = shallowMount(List, { + localVue, + store: fakeStore, + sync: false, + }); + }; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + it('fetches latest pipeline', () => { + createComponent(); + + expect(fetchLatestPipelineMock).toHaveBeenCalled(); + }); + + describe('when loading', () => { + let defaultPipelinesLoadingState; + beforeAll(() => { + defaultPipelinesLoadingState = { + ...defaultState.pipelines, + isLoadingPipeline: true, + }; + }); + + it('does not render when pipeline has loaded before', () => { + createComponent({ + pipelines: { + ...defaultPipelinesLoadingState, + hasLoadedPipeline: true, + }, + }); + + expect(wrapper.find(GlLoadingIcon).exists()).toBe(false); + }); + + it('renders loading state', () => { + createComponent({ + pipelines: { + ...defaultPipelinesLoadingState, + hasLoadedPipeline: false, + }, + }); + + expect(wrapper.find(GlLoadingIcon).exists()).toBe(true); + }); + }); + + describe('when loaded', () => { + let defaultPipelinesLoadedState; + beforeAll(() => { + defaultPipelinesLoadedState = { + ...defaultState.pipelines, + isLoadingPipeline: false, + hasLoadedPipeline: true, + }; + }); + + it('renders empty state when no latestPipeline', () => { + createComponent({ pipelines: { ...defaultPipelinesLoadedState, latestPipeline: null } }); + expect(wrapper.element).toMatchSnapshot(); + }); + + describe('with latest pipeline loaded', () => { + let withLatestPipelineState; + beforeAll(() => { + withLatestPipelineState = { + ...defaultPipelinesLoadedState, + latestPipeline: pipelines[0], + }; + }); + + it('renders ci icon', () => { + createComponent({ pipelines: withLatestPipelineState }); + expect(wrapper.find(CiIcon).exists()).toBe(true); + }); + + it('renders pipeline data', () => { + createComponent({ pipelines: withLatestPipelineState }); + + expect(wrapper.text()).toContain('#1'); + }); + + it('renders list of jobs', () => { + const stages = []; + const isLoadingJobs = true; + createComponent({ pipelines: { ...withLatestPipelineState, stages, isLoadingJobs } }); + + const jobProps = wrapper + .findAll(Tab) + .at(0) + .find(JobsList) + .props(); + expect(jobProps.stages).toBe(stages); + expect(jobProps.loading).toBe(isLoadingJobs); + }); + + it('renders list of failed jobs', () => { + const failedStages = []; + failedStagesGetterMock.mockReset().mockReturnValue(failedStages); + const isLoadingJobs = true; + createComponent({ pipelines: { ...withLatestPipelineState, isLoadingJobs } }); + + const jobProps = wrapper + .findAll(Tab) + .at(1) + .find(JobsList) + .props(); + expect(jobProps.stages).toBe(failedStages); + expect(jobProps.loading).toBe(isLoadingJobs); + }); + + describe('with YAML error', () => { + it('renders YAML error', () => { + const yamlError = 'test yaml error'; + createComponent({ + pipelines: { + ...defaultPipelinesLoadedState, + latestPipeline: { ...pipelines[0], yamlError }, + }, + }); + + expect(wrapper.text()).toContain('Found errors in your .gitlab-ci.yml:'); + expect(wrapper.text()).toContain(yamlError); + }); + }); + }); + }); +}); |