From f521ecd1535ce04ed1688b86ccdb8d45f161e9bf Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Thu, 20 Apr 2017 18:41:21 +0100 Subject: Change spec folder to match the assets one --- spec/javascripts/pipelines/async_button_spec.js | 93 +++++++++++++++++ spec/javascripts/pipelines/empty_state_spec.js | 38 +++++++ spec/javascripts/pipelines/error_state_spec.js | 23 +++++ spec/javascripts/pipelines/mock_data.js | 107 +++++++++++++++++++ spec/javascripts/pipelines/nav_controls_spec.js | 93 +++++++++++++++++ spec/javascripts/pipelines/pipeline_url_spec.js | 100 ++++++++++++++++++ .../pipelines/pipelines_actions_spec.js | 77 ++++++++++++++ .../pipelines/pipelines_artifacts_spec.js | 40 ++++++++ spec/javascripts/pipelines/pipelines_spec.js | 114 +++++++++++++++++++++ spec/javascripts/pipelines/pipelines_store_spec.js | 72 +++++++++++++ spec/javascripts/pipelines/stage_spec.js | 66 ++++++++++++ .../vue_pipelines_index/async_button_spec.js | 93 ----------------- .../vue_pipelines_index/empty_state_spec.js | 38 ------- .../vue_pipelines_index/error_state_spec.js | 23 ----- spec/javascripts/vue_pipelines_index/mock_data.js | 107 ------------------- .../vue_pipelines_index/nav_controls_spec.js | 93 ----------------- .../vue_pipelines_index/pipeline_url_spec.js | 100 ------------------ .../vue_pipelines_index/pipelines_actions_spec.js | 77 -------------- .../pipelines_artifacts_spec.js | 40 -------- .../vue_pipelines_index/pipelines_spec.js | 114 --------------------- .../vue_pipelines_index/pipelines_store_spec.js | 72 ------------- spec/javascripts/vue_pipelines_index/stage_spec.js | 66 ------------ 22 files changed, 823 insertions(+), 823 deletions(-) create mode 100644 spec/javascripts/pipelines/async_button_spec.js create mode 100644 spec/javascripts/pipelines/empty_state_spec.js create mode 100644 spec/javascripts/pipelines/error_state_spec.js create mode 100644 spec/javascripts/pipelines/mock_data.js create mode 100644 spec/javascripts/pipelines/nav_controls_spec.js create mode 100644 spec/javascripts/pipelines/pipeline_url_spec.js create mode 100644 spec/javascripts/pipelines/pipelines_actions_spec.js create mode 100644 spec/javascripts/pipelines/pipelines_artifacts_spec.js create mode 100644 spec/javascripts/pipelines/pipelines_spec.js create mode 100644 spec/javascripts/pipelines/pipelines_store_spec.js create mode 100644 spec/javascripts/pipelines/stage_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/async_button_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/empty_state_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/error_state_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/mock_data.js delete mode 100644 spec/javascripts/vue_pipelines_index/nav_controls_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/pipeline_url_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/pipelines_artifacts_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/pipelines_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/pipelines_store_spec.js delete mode 100644 spec/javascripts/vue_pipelines_index/stage_spec.js diff --git a/spec/javascripts/pipelines/async_button_spec.js b/spec/javascripts/pipelines/async_button_spec.js new file mode 100644 index 00000000000..28c9c7ab282 --- /dev/null +++ b/spec/javascripts/pipelines/async_button_spec.js @@ -0,0 +1,93 @@ +import Vue from 'vue'; +import asyncButtonComp from '~/pipelines/components/async_button.vue'; + +describe('Pipelines Async Button', () => { + let component; + let spy; + let AsyncButtonComponent; + + beforeEach(() => { + AsyncButtonComponent = Vue.extend(asyncButtonComp); + + spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); + + component = new AsyncButtonComponent({ + propsData: { + endpoint: '/foo', + title: 'Foo', + icon: 'fa fa-foo', + cssClass: 'bar', + service: { + postAction: spy, + }, + }, + }).$mount(); + }); + + it('should render a button', () => { + expect(component.$el.tagName).toEqual('BUTTON'); + }); + + it('should render the provided icon', () => { + expect(component.$el.querySelector('i').getAttribute('class')).toContain('fa fa-foo'); + }); + + it('should render the provided title', () => { + expect(component.$el.getAttribute('title')).toContain('Foo'); + expect(component.$el.getAttribute('aria-label')).toContain('Foo'); + }); + + it('should render the provided cssClass', () => { + expect(component.$el.getAttribute('class')).toContain('bar'); + }); + + it('should call the service when it is clicked with the provided endpoint', () => { + component.$el.click(); + expect(spy).toHaveBeenCalledWith('/foo'); + }); + + it('should hide loading if request fails', () => { + spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); + + component = new AsyncButtonComponent({ + propsData: { + endpoint: '/foo', + title: 'Foo', + icon: 'fa fa-foo', + cssClass: 'bar', + dataAttributes: { + 'data-foo': 'foo', + }, + service: { + postAction: spy, + }, + }, + }).$mount(); + + component.$el.click(); + expect(component.$el.querySelector('.fa-spinner')).toBe(null); + }); + + describe('With confirm dialog', () => { + it('should call the service when confimation is positive', () => { + spyOn(window, 'confirm').and.returnValue(true); + spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); + + component = new AsyncButtonComponent({ + propsData: { + endpoint: '/foo', + title: 'Foo', + icon: 'fa fa-foo', + cssClass: 'bar', + service: { + postAction: spy, + }, + confirmActionMessage: 'bar', + }, + }).$mount(); + + component.$el.click(); + expect(spy).toHaveBeenCalledWith('/foo'); + }); + }); +}); diff --git a/spec/javascripts/pipelines/empty_state_spec.js b/spec/javascripts/pipelines/empty_state_spec.js new file mode 100644 index 00000000000..bb47a28d9fe --- /dev/null +++ b/spec/javascripts/pipelines/empty_state_spec.js @@ -0,0 +1,38 @@ +import Vue from 'vue'; +import emptyStateComp from '~/pipelines/components/empty_state.vue'; + +describe('Pipelines Empty State', () => { + let component; + let EmptyStateComponent; + + beforeEach(() => { + EmptyStateComponent = Vue.extend(emptyStateComp); + + component = new EmptyStateComponent({ + propsData: { + helpPagePath: 'foo', + }, + }).$mount(); + }); + + it('should render empty state SVG', () => { + expect(component.$el.querySelector('.svg-content svg')).toBeDefined(); + }); + + it('should render emtpy state information', () => { + expect(component.$el.querySelector('h4').textContent).toContain('Build with confidence'); + + expect( + component.$el.querySelector('p').textContent, + ).toContain('Continous Integration can help catch bugs by running your tests automatically'); + + expect( + component.$el.querySelector('p').textContent, + ).toContain('Continuous Deployment can help you deliver code to your product environment'); + }); + + it('should render a link with provided help path', () => { + expect(component.$el.querySelector('.btn-info').getAttribute('href')).toEqual('foo'); + expect(component.$el.querySelector('.btn-info').textContent).toContain('Get started with Pipelines'); + }); +}); diff --git a/spec/javascripts/pipelines/error_state_spec.js b/spec/javascripts/pipelines/error_state_spec.js new file mode 100644 index 00000000000..f667d351f72 --- /dev/null +++ b/spec/javascripts/pipelines/error_state_spec.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import errorStateComp from '~/pipelines/components/error_state.vue'; + +describe('Pipelines Error State', () => { + let component; + let ErrorStateComponent; + + beforeEach(() => { + ErrorStateComponent = Vue.extend(errorStateComp); + + component = new ErrorStateComponent().$mount(); + }); + + it('should render error state SVG', () => { + expect(component.$el.querySelector('.svg-content svg')).toBeDefined(); + }); + + it('should render emtpy state information', () => { + expect( + component.$el.querySelector('h4').textContent, + ).toContain('The API failed to fetch the pipelines'); + }); +}); diff --git a/spec/javascripts/pipelines/mock_data.js b/spec/javascripts/pipelines/mock_data.js new file mode 100644 index 00000000000..2365a662b9f --- /dev/null +++ b/spec/javascripts/pipelines/mock_data.js @@ -0,0 +1,107 @@ +export default { + pipelines: [{ + id: 115, + user: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + path: '/root/review-app/pipelines/115', + details: { + status: { + icon: 'icon_status_failed', + text: 'failed', + label: 'failed', + group: 'failed', + has_details: true, + details_path: '/root/review-app/pipelines/115', + }, + duration: null, + finished_at: '2017-03-17T19:00:15.996Z', + stages: [{ + name: 'build', + title: 'build: failed', + status: { + icon: 'icon_status_failed', + text: 'failed', + label: 'failed', + group: 'failed', + has_details: true, + details_path: '/root/review-app/pipelines/115#build', + }, + path: '/root/review-app/pipelines/115#build', + dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=build', + }, + { + name: 'review', + title: 'review: skipped', + status: { + icon: 'icon_status_skipped', + text: 'skipped', + label: 'skipped', + group: 'skipped', + has_details: true, + details_path: '/root/review-app/pipelines/115#review', + }, + path: '/root/review-app/pipelines/115#review', + dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=review', + }], + artifacts: [], + manual_actions: [{ + name: 'stop_review', + path: '/root/review-app/builds/3766/play', + }], + }, + flags: { + latest: true, + triggered: false, + stuck: false, + yaml_errors: false, + retryable: true, + cancelable: false, + }, + ref: { + name: 'thisisabranch', + path: '/root/review-app/tree/thisisabranch', + tag: false, + branch: true, + }, + commit: { + id: '9e87f87625b26c42c59a2ee0398f81d20cdfe600', + short_id: '9e87f876', + title: 'Update README.md', + created_at: '2017-03-15T22:58:28.000+00:00', + parent_ids: ['3744f9226e699faec2662a8b267e5d3fd0bfff0e'], + message: 'Update README.md', + author_name: 'Root', + author_email: 'admin@example.com', + authored_date: '2017-03-15T22:58:28.000+00:00', + committer_name: 'Root', + committer_email: 'admin@example.com', + committed_date: '2017-03-15T22:58:28.000+00:00', + author: { + name: 'Root', + username: 'root', + id: 1, + state: 'active', + avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + web_url: 'http://localhost:3000/root', + }, + author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', + commit_url: 'http://localhost:3000/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', + commit_path: '/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', + }, + retry_path: '/root/review-app/pipelines/115/retry', + created_at: '2017-03-15T22:58:33.436Z', + updated_at: '2017-03-17T19:00:15.997Z', + }], + count: { + all: 52, + running: 0, + pending: 0, + finished: 52, + }, +}; diff --git a/spec/javascripts/pipelines/nav_controls_spec.js b/spec/javascripts/pipelines/nav_controls_spec.js new file mode 100644 index 00000000000..601eebce38a --- /dev/null +++ b/spec/javascripts/pipelines/nav_controls_spec.js @@ -0,0 +1,93 @@ +import Vue from 'vue'; +import navControlsComp from '~/pipelines/components/nav_controls'; + +describe('Pipelines Nav Controls', () => { + let NavControlsComponent; + + beforeEach(() => { + NavControlsComponent = Vue.extend(navControlsComp); + }); + + it('should render link to create a new pipeline', () => { + const mockData = { + newPipelinePath: 'foo', + hasCiEnabled: true, + helpPagePath: 'foo', + ciLintPath: 'foo', + canCreatePipeline: true, + }; + + const component = new NavControlsComponent({ + propsData: mockData, + }).$mount(); + + expect(component.$el.querySelector('.btn-create').textContent).toContain('Run Pipeline'); + expect(component.$el.querySelector('.btn-create').getAttribute('href')).toEqual(mockData.newPipelinePath); + }); + + it('should not render link to create pipeline if no permission is provided', () => { + const mockData = { + newPipelinePath: 'foo', + hasCiEnabled: true, + helpPagePath: 'foo', + ciLintPath: 'foo', + canCreatePipeline: false, + }; + + const component = new NavControlsComponent({ + propsData: mockData, + }).$mount(); + + expect(component.$el.querySelector('.btn-create')).toEqual(null); + }); + + it('should render link for CI lint', () => { + const mockData = { + newPipelinePath: 'foo', + hasCiEnabled: true, + helpPagePath: 'foo', + ciLintPath: 'foo', + canCreatePipeline: true, + }; + + const component = new NavControlsComponent({ + propsData: mockData, + }).$mount(); + + expect(component.$el.querySelector('.btn-default').textContent).toContain('CI Lint'); + expect(component.$el.querySelector('.btn-default').getAttribute('href')).toEqual(mockData.ciLintPath); + }); + + it('should render link to help page when CI is not enabled', () => { + const mockData = { + newPipelinePath: 'foo', + hasCiEnabled: false, + helpPagePath: 'foo', + ciLintPath: 'foo', + canCreatePipeline: true, + }; + + const component = new NavControlsComponent({ + propsData: mockData, + }).$mount(); + + expect(component.$el.querySelector('.btn-info').textContent).toContain('Get started with Pipelines'); + expect(component.$el.querySelector('.btn-info').getAttribute('href')).toEqual(mockData.helpPagePath); + }); + + it('should not render link to help page when CI is enabled', () => { + const mockData = { + newPipelinePath: 'foo', + hasCiEnabled: true, + helpPagePath: 'foo', + ciLintPath: 'foo', + canCreatePipeline: true, + }; + + const component = new NavControlsComponent({ + propsData: mockData, + }).$mount(); + + expect(component.$el.querySelector('.btn-info')).toEqual(null); + }); +}); diff --git a/spec/javascripts/pipelines/pipeline_url_spec.js b/spec/javascripts/pipelines/pipeline_url_spec.js new file mode 100644 index 00000000000..53931d67ad7 --- /dev/null +++ b/spec/javascripts/pipelines/pipeline_url_spec.js @@ -0,0 +1,100 @@ +import Vue from 'vue'; +import pipelineUrlComp from '~/pipelines/components/pipeline_url'; + +describe('Pipeline Url Component', () => { + let PipelineUrlComponent; + + beforeEach(() => { + PipelineUrlComponent = Vue.extend(pipelineUrlComp); + }); + + it('should render a table cell', () => { + const component = new PipelineUrlComponent({ + propsData: { + pipeline: { + id: 1, + path: 'foo', + flags: {}, + }, + }, + }).$mount(); + + expect(component.$el.tagName).toEqual('TD'); + }); + + it('should render a link the provided path and id', () => { + const component = new PipelineUrlComponent({ + propsData: { + pipeline: { + id: 1, + path: 'foo', + flags: {}, + }, + }, + }).$mount(); + + expect(component.$el.querySelector('.js-pipeline-url-link').getAttribute('href')).toEqual('foo'); + expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1'); + }); + + it('should render user information when a user is provided', () => { + const mockData = { + pipeline: { + id: 1, + path: 'foo', + flags: {}, + user: { + web_url: '/', + name: 'foo', + avatar_url: '/', + }, + }, + }; + + const component = new PipelineUrlComponent({ + propsData: mockData, + }).$mount(); + + const image = component.$el.querySelector('.js-pipeline-url-user img'); + + expect( + component.$el.querySelector('.js-pipeline-url-user').getAttribute('href'), + ).toEqual(mockData.pipeline.user.web_url); + expect(image.getAttribute('title')).toEqual(mockData.pipeline.user.name); + expect(image.getAttribute('src')).toEqual(mockData.pipeline.user.avatar_url); + }); + + it('should render "API" when no user is provided', () => { + const component = new PipelineUrlComponent({ + propsData: { + pipeline: { + id: 1, + path: 'foo', + flags: {}, + }, + }, + }).$mount(); + + expect(component.$el.querySelector('.js-pipeline-url-api').textContent).toContain('API'); + }); + + it('should render latest, yaml invalid and stuck flags when provided', () => { + const component = new PipelineUrlComponent({ + propsData: { + pipeline: { + id: 1, + path: 'foo', + flags: { + latest: true, + yaml_errors: true, + stuck: true, + }, + }, + }, + }).$mount(); + + expect(component.$el.querySelector('.js-pipeline-url-lastest').textContent).toContain('latest'); + expect(component.$el.querySelector('.js-pipeline-url-yaml').textContent).toContain('yaml invalid'); + expect(component.$el.querySelector('.js-pipeline-url-stuck').textContent).toContain('stuck'); + }); +}); diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js new file mode 100644 index 00000000000..c89dacbcd93 --- /dev/null +++ b/spec/javascripts/pipelines/pipelines_actions_spec.js @@ -0,0 +1,77 @@ +import Vue from 'vue'; +import pipelinesActionsComp from '~/pipelines/components/pipelines_actions'; + +describe('Pipelines Actions dropdown', () => { + let component; + let spy; + let actions; + let ActionsComponent; + + beforeEach(() => { + ActionsComponent = Vue.extend(pipelinesActionsComp); + + actions = [ + { + name: 'stop_review', + path: '/root/review-app/builds/1893/play', + }, + { + name: 'foo', + path: '#', + playable: false, + }, + ]; + + spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); + + component = new ActionsComponent({ + propsData: { + actions, + service: { + postAction: spy, + }, + }, + }).$mount(); + }); + + it('should render a dropdown with the provided actions', () => { + expect( + component.$el.querySelectorAll('.dropdown-menu li').length, + ).toEqual(actions.length); + }); + + it('should call the service when an action is clicked', () => { + component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); + component.$el.querySelector('.js-pipeline-action-link').click(); + + expect(spy).toHaveBeenCalledWith(actions[0].path); + }); + + it('should hide loading if request fails', () => { + spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); + + component = new ActionsComponent({ + propsData: { + actions, + service: { + postAction: spy, + }, + }, + }).$mount(); + + component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); + component.$el.querySelector('.js-pipeline-action-link').click(); + + expect(component.$el.querySelector('.fa-spinner')).toEqual(null); + }); + + it('should render a disabled action when it\'s not playable', () => { + expect( + component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'), + ).toEqual('disabled'); + + expect( + component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'), + ).toEqual(true); + }); +}); diff --git a/spec/javascripts/pipelines/pipelines_artifacts_spec.js b/spec/javascripts/pipelines/pipelines_artifacts_spec.js new file mode 100644 index 00000000000..9724b63d957 --- /dev/null +++ b/spec/javascripts/pipelines/pipelines_artifacts_spec.js @@ -0,0 +1,40 @@ +import Vue from 'vue'; +import artifactsComp from '~/pipelines/components/pipelines_artifacts'; + +describe('Pipelines Artifacts dropdown', () => { + let component; + let artifacts; + + beforeEach(() => { + const ArtifactsComponent = Vue.extend(artifactsComp); + + artifacts = [ + { + name: 'artifact', + path: '/download/path', + }, + ]; + + component = new ArtifactsComponent({ + propsData: { + artifacts, + }, + }).$mount(); + }); + + it('should render a dropdown with the provided artifacts', () => { + expect( + component.$el.querySelectorAll('.dropdown-menu li').length, + ).toEqual(artifacts.length); + }); + + it('should render a link with the provided path', () => { + expect( + component.$el.querySelector('.dropdown-menu li a').getAttribute('href'), + ).toEqual(artifacts[0].path); + + expect( + component.$el.querySelector('.dropdown-menu li a span').textContent, + ).toContain(artifacts[0].name); + }); +}); diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js new file mode 100644 index 00000000000..e9c05f74ce6 --- /dev/null +++ b/spec/javascripts/pipelines/pipelines_spec.js @@ -0,0 +1,114 @@ +import Vue from 'vue'; +import pipelinesComp from '~/pipelines/pipelines'; +import Store from '~/pipelines/stores/pipelines_store'; +import pipelinesData from './mock_data'; + +describe('Pipelines', () => { + preloadFixtures('static/pipelines.html.raw'); + + let PipelinesComponent; + + beforeEach(() => { + loadFixtures('static/pipelines.html.raw'); + + PipelinesComponent = Vue.extend(pipelinesComp); + }); + + describe('successfull request', () => { + describe('with pipelines', () => { + const pipelinesInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify(pipelinesData), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(pipelinesInterceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, pipelinesInterceptor, + ); + }); + + it('should render table', (done) => { + const component = new PipelinesComponent({ + propsData: { + store: new Store(), + }, + }).$mount(); + + setTimeout(() => { + expect(component.$el.querySelector('.table-holder')).toBeDefined(); + expect(component.$el.querySelector('.realtime-loading')).toBe(null); + done(); + }); + }); + }); + + describe('without pipelines', () => { + const emptyInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 200, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(emptyInterceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, emptyInterceptor, + ); + }); + + it('should render empty state', (done) => { + const component = new PipelinesComponent({ + propsData: { + store: new Store(), + }, + }).$mount(); + + setTimeout(() => { + expect(component.$el.querySelector('.empty-state')).toBeDefined(); + expect(component.$el.querySelector('.realtime-loading')).toBe(null); + done(); + }); + }); + }); + }); + + describe('unsuccessfull request', () => { + const errorInterceptor = (request, next) => { + next(request.respondWith(JSON.stringify([]), { + status: 500, + })); + }; + + beforeEach(() => { + Vue.http.interceptors.push(errorInterceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without( + Vue.http.interceptors, errorInterceptor, + ); + }); + + it('should render error state', (done) => { + const component = new PipelinesComponent({ + propsData: { + store: new Store(), + }, + }).$mount(); + + setTimeout(() => { + expect(component.$el.querySelector('.js-pipelines-error-state')).toBeDefined(); + expect(component.$el.querySelector('.realtime-loading')).toBe(null); + done(); + }); + }); + }); +}); diff --git a/spec/javascripts/pipelines/pipelines_store_spec.js b/spec/javascripts/pipelines/pipelines_store_spec.js new file mode 100644 index 00000000000..10ff0c6bb84 --- /dev/null +++ b/spec/javascripts/pipelines/pipelines_store_spec.js @@ -0,0 +1,72 @@ +import PipelineStore from '~/pipelines/stores/pipelines_store'; + +describe('Pipelines Store', () => { + let store; + + beforeEach(() => { + store = new PipelineStore(); + }); + + it('should be initialized with an empty state', () => { + expect(store.state.pipelines).toEqual([]); + expect(store.state.count).toEqual({}); + expect(store.state.pageInfo).toEqual({}); + }); + + describe('storePipelines', () => { + it('should use the default parameter if none is provided', () => { + store.storePipelines(); + expect(store.state.pipelines).toEqual([]); + }); + + it('should store the provided array', () => { + const array = [{ id: 1, status: 'running' }, { id: 2, status: 'success' }]; + store.storePipelines(array); + expect(store.state.pipelines).toEqual(array); + }); + }); + + describe('storeCount', () => { + it('should use the default parameter if none is provided', () => { + store.storeCount(); + expect(store.state.count).toEqual({}); + }); + + it('should store the provided count', () => { + const count = { all: 20, finished: 10 }; + store.storeCount(count); + + expect(store.state.count).toEqual(count); + }); + }); + + describe('storePagination', () => { + it('should use the default parameter if none is provided', () => { + store.storePagination(); + expect(store.state.pageInfo).toEqual({}); + }); + + it('should store pagination information normalized and parsed', () => { + const pagination = { + 'X-nExt-pAge': '2', + 'X-page': '1', + 'X-Per-Page': '1', + 'X-Prev-Page': '2', + 'X-TOTAL': '37', + 'X-Total-Pages': '2', + }; + + const expectedResult = { + perPage: 1, + page: 1, + total: 37, + totalPages: 2, + nextPage: 2, + previousPage: 2, + }; + + store.storePagination(pagination); + expect(store.state.pageInfo).toEqual(expectedResult); + }); + }); +}); diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js new file mode 100644 index 00000000000..66b57a82363 --- /dev/null +++ b/spec/javascripts/pipelines/stage_spec.js @@ -0,0 +1,66 @@ +import Vue from 'vue'; +import { SUCCESS_SVG } from '~/ci_status_icons'; +import Stage from '~/pipelines/components/stage'; + +function minify(string) { + return string.replace(/\s/g, ''); +} + +describe('Pipelines Stage', () => { + describe('data', () => { + let stageReturnValue; + + beforeEach(() => { + stageReturnValue = Stage.data(); + }); + + it('should return object with .builds and .spinner', () => { + expect(stageReturnValue).toEqual({ + builds: '', + spinner: '', + }); + }); + }); + + describe('computed', () => { + describe('svgHTML', function () { + let stage; + let svgHTML; + + beforeEach(() => { + stage = { stage: { status: { icon: 'icon_status_success' } } }; + + svgHTML = Stage.computed.svgHTML.call(stage); + }); + + it("should return the correct icon for the stage's status", () => { + expect(svgHTML).toBe(SUCCESS_SVG); + }); + }); + }); + + describe('when mounted', () => { + let StageComponent; + let renderedComponent; + let stage; + + beforeEach(() => { + stage = { status: { icon: 'icon_status_success' } }; + + StageComponent = Vue.extend(Stage); + + renderedComponent = new StageComponent({ + propsData: { + stage, + }, + }).$mount(); + }); + + it('should render the correct status svg', () => { + const minifiedComponent = minify(renderedComponent.$el.outerHTML); + const expectedSVG = minify(SUCCESS_SVG); + + expect(minifiedComponent).toContain(expectedSVG); + }); + }); +}); diff --git a/spec/javascripts/vue_pipelines_index/async_button_spec.js b/spec/javascripts/vue_pipelines_index/async_button_spec.js deleted file mode 100644 index 28c9c7ab282..00000000000 --- a/spec/javascripts/vue_pipelines_index/async_button_spec.js +++ /dev/null @@ -1,93 +0,0 @@ -import Vue from 'vue'; -import asyncButtonComp from '~/pipelines/components/async_button.vue'; - -describe('Pipelines Async Button', () => { - let component; - let spy; - let AsyncButtonComponent; - - beforeEach(() => { - AsyncButtonComponent = Vue.extend(asyncButtonComp); - - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); - - component = new AsyncButtonComponent({ - propsData: { - endpoint: '/foo', - title: 'Foo', - icon: 'fa fa-foo', - cssClass: 'bar', - service: { - postAction: spy, - }, - }, - }).$mount(); - }); - - it('should render a button', () => { - expect(component.$el.tagName).toEqual('BUTTON'); - }); - - it('should render the provided icon', () => { - expect(component.$el.querySelector('i').getAttribute('class')).toContain('fa fa-foo'); - }); - - it('should render the provided title', () => { - expect(component.$el.getAttribute('title')).toContain('Foo'); - expect(component.$el.getAttribute('aria-label')).toContain('Foo'); - }); - - it('should render the provided cssClass', () => { - expect(component.$el.getAttribute('class')).toContain('bar'); - }); - - it('should call the service when it is clicked with the provided endpoint', () => { - component.$el.click(); - expect(spy).toHaveBeenCalledWith('/foo'); - }); - - it('should hide loading if request fails', () => { - spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); - - component = new AsyncButtonComponent({ - propsData: { - endpoint: '/foo', - title: 'Foo', - icon: 'fa fa-foo', - cssClass: 'bar', - dataAttributes: { - 'data-foo': 'foo', - }, - service: { - postAction: spy, - }, - }, - }).$mount(); - - component.$el.click(); - expect(component.$el.querySelector('.fa-spinner')).toBe(null); - }); - - describe('With confirm dialog', () => { - it('should call the service when confimation is positive', () => { - spyOn(window, 'confirm').and.returnValue(true); - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); - - component = new AsyncButtonComponent({ - propsData: { - endpoint: '/foo', - title: 'Foo', - icon: 'fa fa-foo', - cssClass: 'bar', - service: { - postAction: spy, - }, - confirmActionMessage: 'bar', - }, - }).$mount(); - - component.$el.click(); - expect(spy).toHaveBeenCalledWith('/foo'); - }); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/empty_state_spec.js b/spec/javascripts/vue_pipelines_index/empty_state_spec.js deleted file mode 100644 index bb47a28d9fe..00000000000 --- a/spec/javascripts/vue_pipelines_index/empty_state_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -import Vue from 'vue'; -import emptyStateComp from '~/pipelines/components/empty_state.vue'; - -describe('Pipelines Empty State', () => { - let component; - let EmptyStateComponent; - - beforeEach(() => { - EmptyStateComponent = Vue.extend(emptyStateComp); - - component = new EmptyStateComponent({ - propsData: { - helpPagePath: 'foo', - }, - }).$mount(); - }); - - it('should render empty state SVG', () => { - expect(component.$el.querySelector('.svg-content svg')).toBeDefined(); - }); - - it('should render emtpy state information', () => { - expect(component.$el.querySelector('h4').textContent).toContain('Build with confidence'); - - expect( - component.$el.querySelector('p').textContent, - ).toContain('Continous Integration can help catch bugs by running your tests automatically'); - - expect( - component.$el.querySelector('p').textContent, - ).toContain('Continuous Deployment can help you deliver code to your product environment'); - }); - - it('should render a link with provided help path', () => { - expect(component.$el.querySelector('.btn-info').getAttribute('href')).toEqual('foo'); - expect(component.$el.querySelector('.btn-info').textContent).toContain('Get started with Pipelines'); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/error_state_spec.js b/spec/javascripts/vue_pipelines_index/error_state_spec.js deleted file mode 100644 index f667d351f72..00000000000 --- a/spec/javascripts/vue_pipelines_index/error_state_spec.js +++ /dev/null @@ -1,23 +0,0 @@ -import Vue from 'vue'; -import errorStateComp from '~/pipelines/components/error_state.vue'; - -describe('Pipelines Error State', () => { - let component; - let ErrorStateComponent; - - beforeEach(() => { - ErrorStateComponent = Vue.extend(errorStateComp); - - component = new ErrorStateComponent().$mount(); - }); - - it('should render error state SVG', () => { - expect(component.$el.querySelector('.svg-content svg')).toBeDefined(); - }); - - it('should render emtpy state information', () => { - expect( - component.$el.querySelector('h4').textContent, - ).toContain('The API failed to fetch the pipelines'); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/mock_data.js b/spec/javascripts/vue_pipelines_index/mock_data.js deleted file mode 100644 index 2365a662b9f..00000000000 --- a/spec/javascripts/vue_pipelines_index/mock_data.js +++ /dev/null @@ -1,107 +0,0 @@ -export default { - pipelines: [{ - id: 115, - user: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - web_url: 'http://localhost:3000/root', - }, - path: '/root/review-app/pipelines/115', - details: { - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/115', - }, - duration: null, - finished_at: '2017-03-17T19:00:15.996Z', - stages: [{ - name: 'build', - title: 'build: failed', - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/115#build', - }, - path: '/root/review-app/pipelines/115#build', - dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=build', - }, - { - name: 'review', - title: 'review: skipped', - status: { - icon: 'icon_status_skipped', - text: 'skipped', - label: 'skipped', - group: 'skipped', - has_details: true, - details_path: '/root/review-app/pipelines/115#review', - }, - path: '/root/review-app/pipelines/115#review', - dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=review', - }], - artifacts: [], - manual_actions: [{ - name: 'stop_review', - path: '/root/review-app/builds/3766/play', - }], - }, - flags: { - latest: true, - triggered: false, - stuck: false, - yaml_errors: false, - retryable: true, - cancelable: false, - }, - ref: { - name: 'thisisabranch', - path: '/root/review-app/tree/thisisabranch', - tag: false, - branch: true, - }, - commit: { - id: '9e87f87625b26c42c59a2ee0398f81d20cdfe600', - short_id: '9e87f876', - title: 'Update README.md', - created_at: '2017-03-15T22:58:28.000+00:00', - parent_ids: ['3744f9226e699faec2662a8b267e5d3fd0bfff0e'], - message: 'Update README.md', - author_name: 'Root', - author_email: 'admin@example.com', - authored_date: '2017-03-15T22:58:28.000+00:00', - committer_name: 'Root', - committer_email: 'admin@example.com', - committed_date: '2017-03-15T22:58:28.000+00:00', - author: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - web_url: 'http://localhost:3000/root', - }, - author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - commit_url: 'http://localhost:3000/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', - commit_path: '/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', - }, - retry_path: '/root/review-app/pipelines/115/retry', - created_at: '2017-03-15T22:58:33.436Z', - updated_at: '2017-03-17T19:00:15.997Z', - }], - count: { - all: 52, - running: 0, - pending: 0, - finished: 52, - }, -}; diff --git a/spec/javascripts/vue_pipelines_index/nav_controls_spec.js b/spec/javascripts/vue_pipelines_index/nav_controls_spec.js deleted file mode 100644 index 601eebce38a..00000000000 --- a/spec/javascripts/vue_pipelines_index/nav_controls_spec.js +++ /dev/null @@ -1,93 +0,0 @@ -import Vue from 'vue'; -import navControlsComp from '~/pipelines/components/nav_controls'; - -describe('Pipelines Nav Controls', () => { - let NavControlsComponent; - - beforeEach(() => { - NavControlsComponent = Vue.extend(navControlsComp); - }); - - it('should render link to create a new pipeline', () => { - const mockData = { - newPipelinePath: 'foo', - hasCiEnabled: true, - helpPagePath: 'foo', - ciLintPath: 'foo', - canCreatePipeline: true, - }; - - const component = new NavControlsComponent({ - propsData: mockData, - }).$mount(); - - expect(component.$el.querySelector('.btn-create').textContent).toContain('Run Pipeline'); - expect(component.$el.querySelector('.btn-create').getAttribute('href')).toEqual(mockData.newPipelinePath); - }); - - it('should not render link to create pipeline if no permission is provided', () => { - const mockData = { - newPipelinePath: 'foo', - hasCiEnabled: true, - helpPagePath: 'foo', - ciLintPath: 'foo', - canCreatePipeline: false, - }; - - const component = new NavControlsComponent({ - propsData: mockData, - }).$mount(); - - expect(component.$el.querySelector('.btn-create')).toEqual(null); - }); - - it('should render link for CI lint', () => { - const mockData = { - newPipelinePath: 'foo', - hasCiEnabled: true, - helpPagePath: 'foo', - ciLintPath: 'foo', - canCreatePipeline: true, - }; - - const component = new NavControlsComponent({ - propsData: mockData, - }).$mount(); - - expect(component.$el.querySelector('.btn-default').textContent).toContain('CI Lint'); - expect(component.$el.querySelector('.btn-default').getAttribute('href')).toEqual(mockData.ciLintPath); - }); - - it('should render link to help page when CI is not enabled', () => { - const mockData = { - newPipelinePath: 'foo', - hasCiEnabled: false, - helpPagePath: 'foo', - ciLintPath: 'foo', - canCreatePipeline: true, - }; - - const component = new NavControlsComponent({ - propsData: mockData, - }).$mount(); - - expect(component.$el.querySelector('.btn-info').textContent).toContain('Get started with Pipelines'); - expect(component.$el.querySelector('.btn-info').getAttribute('href')).toEqual(mockData.helpPagePath); - }); - - it('should not render link to help page when CI is enabled', () => { - const mockData = { - newPipelinePath: 'foo', - hasCiEnabled: true, - helpPagePath: 'foo', - ciLintPath: 'foo', - canCreatePipeline: true, - }; - - const component = new NavControlsComponent({ - propsData: mockData, - }).$mount(); - - expect(component.$el.querySelector('.btn-info')).toEqual(null); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/pipeline_url_spec.js b/spec/javascripts/vue_pipelines_index/pipeline_url_spec.js deleted file mode 100644 index 53931d67ad7..00000000000 --- a/spec/javascripts/vue_pipelines_index/pipeline_url_spec.js +++ /dev/null @@ -1,100 +0,0 @@ -import Vue from 'vue'; -import pipelineUrlComp from '~/pipelines/components/pipeline_url'; - -describe('Pipeline Url Component', () => { - let PipelineUrlComponent; - - beforeEach(() => { - PipelineUrlComponent = Vue.extend(pipelineUrlComp); - }); - - it('should render a table cell', () => { - const component = new PipelineUrlComponent({ - propsData: { - pipeline: { - id: 1, - path: 'foo', - flags: {}, - }, - }, - }).$mount(); - - expect(component.$el.tagName).toEqual('TD'); - }); - - it('should render a link the provided path and id', () => { - const component = new PipelineUrlComponent({ - propsData: { - pipeline: { - id: 1, - path: 'foo', - flags: {}, - }, - }, - }).$mount(); - - expect(component.$el.querySelector('.js-pipeline-url-link').getAttribute('href')).toEqual('foo'); - expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1'); - }); - - it('should render user information when a user is provided', () => { - const mockData = { - pipeline: { - id: 1, - path: 'foo', - flags: {}, - user: { - web_url: '/', - name: 'foo', - avatar_url: '/', - }, - }, - }; - - const component = new PipelineUrlComponent({ - propsData: mockData, - }).$mount(); - - const image = component.$el.querySelector('.js-pipeline-url-user img'); - - expect( - component.$el.querySelector('.js-pipeline-url-user').getAttribute('href'), - ).toEqual(mockData.pipeline.user.web_url); - expect(image.getAttribute('title')).toEqual(mockData.pipeline.user.name); - expect(image.getAttribute('src')).toEqual(mockData.pipeline.user.avatar_url); - }); - - it('should render "API" when no user is provided', () => { - const component = new PipelineUrlComponent({ - propsData: { - pipeline: { - id: 1, - path: 'foo', - flags: {}, - }, - }, - }).$mount(); - - expect(component.$el.querySelector('.js-pipeline-url-api').textContent).toContain('API'); - }); - - it('should render latest, yaml invalid and stuck flags when provided', () => { - const component = new PipelineUrlComponent({ - propsData: { - pipeline: { - id: 1, - path: 'foo', - flags: { - latest: true, - yaml_errors: true, - stuck: true, - }, - }, - }, - }).$mount(); - - expect(component.$el.querySelector('.js-pipeline-url-lastest').textContent).toContain('latest'); - expect(component.$el.querySelector('.js-pipeline-url-yaml').textContent).toContain('yaml invalid'); - expect(component.$el.querySelector('.js-pipeline-url-stuck').textContent).toContain('stuck'); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js deleted file mode 100644 index c89dacbcd93..00000000000 --- a/spec/javascripts/vue_pipelines_index/pipelines_actions_spec.js +++ /dev/null @@ -1,77 +0,0 @@ -import Vue from 'vue'; -import pipelinesActionsComp from '~/pipelines/components/pipelines_actions'; - -describe('Pipelines Actions dropdown', () => { - let component; - let spy; - let actions; - let ActionsComponent; - - beforeEach(() => { - ActionsComponent = Vue.extend(pipelinesActionsComp); - - actions = [ - { - name: 'stop_review', - path: '/root/review-app/builds/1893/play', - }, - { - name: 'foo', - path: '#', - playable: false, - }, - ]; - - spy = jasmine.createSpy('spy').and.returnValue(Promise.resolve()); - - component = new ActionsComponent({ - propsData: { - actions, - service: { - postAction: spy, - }, - }, - }).$mount(); - }); - - it('should render a dropdown with the provided actions', () => { - expect( - component.$el.querySelectorAll('.dropdown-menu li').length, - ).toEqual(actions.length); - }); - - it('should call the service when an action is clicked', () => { - component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); - component.$el.querySelector('.js-pipeline-action-link').click(); - - expect(spy).toHaveBeenCalledWith(actions[0].path); - }); - - it('should hide loading if request fails', () => { - spy = jasmine.createSpy('spy').and.returnValue(Promise.reject()); - - component = new ActionsComponent({ - propsData: { - actions, - service: { - postAction: spy, - }, - }, - }).$mount(); - - component.$el.querySelector('.js-pipeline-dropdown-manual-actions').click(); - component.$el.querySelector('.js-pipeline-action-link').click(); - - expect(component.$el.querySelector('.fa-spinner')).toEqual(null); - }); - - it('should render a disabled action when it\'s not playable', () => { - expect( - component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'), - ).toEqual('disabled'); - - expect( - component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'), - ).toEqual(true); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/pipelines_artifacts_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_artifacts_spec.js deleted file mode 100644 index 9724b63d957..00000000000 --- a/spec/javascripts/vue_pipelines_index/pipelines_artifacts_spec.js +++ /dev/null @@ -1,40 +0,0 @@ -import Vue from 'vue'; -import artifactsComp from '~/pipelines/components/pipelines_artifacts'; - -describe('Pipelines Artifacts dropdown', () => { - let component; - let artifacts; - - beforeEach(() => { - const ArtifactsComponent = Vue.extend(artifactsComp); - - artifacts = [ - { - name: 'artifact', - path: '/download/path', - }, - ]; - - component = new ArtifactsComponent({ - propsData: { - artifacts, - }, - }).$mount(); - }); - - it('should render a dropdown with the provided artifacts', () => { - expect( - component.$el.querySelectorAll('.dropdown-menu li').length, - ).toEqual(artifacts.length); - }); - - it('should render a link with the provided path', () => { - expect( - component.$el.querySelector('.dropdown-menu li a').getAttribute('href'), - ).toEqual(artifacts[0].path); - - expect( - component.$el.querySelector('.dropdown-menu li a span').textContent, - ).toContain(artifacts[0].name); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/pipelines_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_spec.js deleted file mode 100644 index e9c05f74ce6..00000000000 --- a/spec/javascripts/vue_pipelines_index/pipelines_spec.js +++ /dev/null @@ -1,114 +0,0 @@ -import Vue from 'vue'; -import pipelinesComp from '~/pipelines/pipelines'; -import Store from '~/pipelines/stores/pipelines_store'; -import pipelinesData from './mock_data'; - -describe('Pipelines', () => { - preloadFixtures('static/pipelines.html.raw'); - - let PipelinesComponent; - - beforeEach(() => { - loadFixtures('static/pipelines.html.raw'); - - PipelinesComponent = Vue.extend(pipelinesComp); - }); - - describe('successfull request', () => { - describe('with pipelines', () => { - const pipelinesInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify(pipelinesData), { - status: 200, - })); - }; - - beforeEach(() => { - Vue.http.interceptors.push(pipelinesInterceptor); - }); - - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, pipelinesInterceptor, - ); - }); - - it('should render table', (done) => { - const component = new PipelinesComponent({ - propsData: { - store: new Store(), - }, - }).$mount(); - - setTimeout(() => { - expect(component.$el.querySelector('.table-holder')).toBeDefined(); - expect(component.$el.querySelector('.realtime-loading')).toBe(null); - done(); - }); - }); - }); - - describe('without pipelines', () => { - const emptyInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify([]), { - status: 200, - })); - }; - - beforeEach(() => { - Vue.http.interceptors.push(emptyInterceptor); - }); - - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, emptyInterceptor, - ); - }); - - it('should render empty state', (done) => { - const component = new PipelinesComponent({ - propsData: { - store: new Store(), - }, - }).$mount(); - - setTimeout(() => { - expect(component.$el.querySelector('.empty-state')).toBeDefined(); - expect(component.$el.querySelector('.realtime-loading')).toBe(null); - done(); - }); - }); - }); - }); - - describe('unsuccessfull request', () => { - const errorInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify([]), { - status: 500, - })); - }; - - beforeEach(() => { - Vue.http.interceptors.push(errorInterceptor); - }); - - afterEach(() => { - Vue.http.interceptors = _.without( - Vue.http.interceptors, errorInterceptor, - ); - }); - - it('should render error state', (done) => { - const component = new PipelinesComponent({ - propsData: { - store: new Store(), - }, - }).$mount(); - - setTimeout(() => { - expect(component.$el.querySelector('.js-pipelines-error-state')).toBeDefined(); - expect(component.$el.querySelector('.realtime-loading')).toBe(null); - done(); - }); - }); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/pipelines_store_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_store_spec.js deleted file mode 100644 index 10ff0c6bb84..00000000000 --- a/spec/javascripts/vue_pipelines_index/pipelines_store_spec.js +++ /dev/null @@ -1,72 +0,0 @@ -import PipelineStore from '~/pipelines/stores/pipelines_store'; - -describe('Pipelines Store', () => { - let store; - - beforeEach(() => { - store = new PipelineStore(); - }); - - it('should be initialized with an empty state', () => { - expect(store.state.pipelines).toEqual([]); - expect(store.state.count).toEqual({}); - expect(store.state.pageInfo).toEqual({}); - }); - - describe('storePipelines', () => { - it('should use the default parameter if none is provided', () => { - store.storePipelines(); - expect(store.state.pipelines).toEqual([]); - }); - - it('should store the provided array', () => { - const array = [{ id: 1, status: 'running' }, { id: 2, status: 'success' }]; - store.storePipelines(array); - expect(store.state.pipelines).toEqual(array); - }); - }); - - describe('storeCount', () => { - it('should use the default parameter if none is provided', () => { - store.storeCount(); - expect(store.state.count).toEqual({}); - }); - - it('should store the provided count', () => { - const count = { all: 20, finished: 10 }; - store.storeCount(count); - - expect(store.state.count).toEqual(count); - }); - }); - - describe('storePagination', () => { - it('should use the default parameter if none is provided', () => { - store.storePagination(); - expect(store.state.pageInfo).toEqual({}); - }); - - it('should store pagination information normalized and parsed', () => { - const pagination = { - 'X-nExt-pAge': '2', - 'X-page': '1', - 'X-Per-Page': '1', - 'X-Prev-Page': '2', - 'X-TOTAL': '37', - 'X-Total-Pages': '2', - }; - - const expectedResult = { - perPage: 1, - page: 1, - total: 37, - totalPages: 2, - nextPage: 2, - previousPage: 2, - }; - - store.storePagination(pagination); - expect(store.state.pageInfo).toEqual(expectedResult); - }); - }); -}); diff --git a/spec/javascripts/vue_pipelines_index/stage_spec.js b/spec/javascripts/vue_pipelines_index/stage_spec.js deleted file mode 100644 index 66b57a82363..00000000000 --- a/spec/javascripts/vue_pipelines_index/stage_spec.js +++ /dev/null @@ -1,66 +0,0 @@ -import Vue from 'vue'; -import { SUCCESS_SVG } from '~/ci_status_icons'; -import Stage from '~/pipelines/components/stage'; - -function minify(string) { - return string.replace(/\s/g, ''); -} - -describe('Pipelines Stage', () => { - describe('data', () => { - let stageReturnValue; - - beforeEach(() => { - stageReturnValue = Stage.data(); - }); - - it('should return object with .builds and .spinner', () => { - expect(stageReturnValue).toEqual({ - builds: '', - spinner: '', - }); - }); - }); - - describe('computed', () => { - describe('svgHTML', function () { - let stage; - let svgHTML; - - beforeEach(() => { - stage = { stage: { status: { icon: 'icon_status_success' } } }; - - svgHTML = Stage.computed.svgHTML.call(stage); - }); - - it("should return the correct icon for the stage's status", () => { - expect(svgHTML).toBe(SUCCESS_SVG); - }); - }); - }); - - describe('when mounted', () => { - let StageComponent; - let renderedComponent; - let stage; - - beforeEach(() => { - stage = { status: { icon: 'icon_status_success' } }; - - StageComponent = Vue.extend(Stage); - - renderedComponent = new StageComponent({ - propsData: { - stage, - }, - }).$mount(); - }); - - it('should render the correct status svg', () => { - const minifiedComponent = minify(renderedComponent.$el.outerHTML); - const expectedSVG = minify(SUCCESS_SVG); - - expect(minifiedComponent).toContain(expectedSVG); - }); - }); -}); -- cgit v1.2.1