diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2017-03-20 15:36:02 +0000 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2017-03-20 16:16:19 +0000 |
commit | 446b59dd4ee88f8ef86272c39408560a0107c48a (patch) | |
tree | dc6eef4b89111775dd4176f6db08fd95af57c293 /spec/javascripts | |
parent | 2c85a20482c2e33f307ad8faf60e41e199aa25b8 (diff) | |
download | gitlab-ce-446b59dd4ee88f8ef86272c39408560a0107c48a.tar.gz |
Adds tests to new empty and error states
Diffstat (limited to 'spec/javascripts')
7 files changed, 388 insertions, 2 deletions
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js index 75efcc06585..cb51e6f3ef3 100644 --- a/spec/javascripts/commit/pipelines/pipelines_spec.js +++ b/spec/javascripts/commit/pipelines/pipelines_spec.js @@ -33,7 +33,7 @@ describe('Pipelines table in Commits and Merge requests', () => { }); setTimeout(() => { - expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain('No pipelines to show'); + expect(component.$el.querySelector('.js-pipelines-empty-state')).toBeDefined(); done(); }, 1); }); @@ -92,7 +92,7 @@ describe('Pipelines table in Commits and Merge requests', () => { }); setTimeout(() => { - expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain('No pipelines to show'); + expect(component.$el.querySelector('.js-pipelines-error-state')).toBeDefined(); done(); }, 0); }); diff --git a/spec/javascripts/fixtures/pipelines.html.haml b/spec/javascripts/fixtures/pipelines.html.haml new file mode 100644 index 00000000000..418a38a0e2e --- /dev/null +++ b/spec/javascripts/fixtures/pipelines.html.haml @@ -0,0 +1,14 @@ +%div + #pipelines-list-vue{ data: { endpoint: 'foo', + "css-class" => 'foo', + "help-page-path" => 'foo', + "new-pipeline-path" => 'foo', + "can-create-pipeline" => 'true', + "all-path" => 'foo', + "pending-path" => 'foo', + "running-path" => 'foo', + "finished-path" => 'foo', + "branches-path" => 'foo', + "tags-path" => 'foo', + "has-ci" => 'foo', + "ci-lint-path" => 'foo' } } diff --git a/spec/javascripts/vue_pipelines_index/empty_state_spec.js b/spec/javascripts/vue_pipelines_index/empty_state_spec.js new file mode 100644 index 00000000000..733337168dc --- /dev/null +++ b/spec/javascripts/vue_pipelines_index/empty_state_spec.js @@ -0,0 +1,38 @@ +import Vue from 'vue'; +import emptyStateComp from '~/vue_pipelines_index/components/empty_state'; + +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 new file mode 100644 index 00000000000..524e018b1fa --- /dev/null +++ b/spec/javascripts/vue_pipelines_index/error_state_spec.js @@ -0,0 +1,23 @@ +import Vue from 'vue'; +import errorStateComp from '~/vue_pipelines_index/components/error_state'; + +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 new file mode 100644 index 00000000000..2365a662b9f --- /dev/null +++ b/spec/javascripts/vue_pipelines_index/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/vue_pipelines_index/nav_controls_spec.js b/spec/javascripts/vue_pipelines_index/nav_controls_spec.js new file mode 100644 index 00000000000..8283e53c8b1 --- /dev/null +++ b/spec/javascripts/vue_pipelines_index/nav_controls_spec.js @@ -0,0 +1,93 @@ +import Vue from 'vue'; +import navControlsComp from '~/vue_pipelines_index/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/pipelines_spec.js b/spec/javascripts/vue_pipelines_index/pipelines_spec.js new file mode 100644 index 00000000000..22d1c4e16a3 --- /dev/null +++ b/spec/javascripts/vue_pipelines_index/pipelines_spec.js @@ -0,0 +1,111 @@ +import Vue from 'vue'; +import pipelinesComp from '~/vue_pipelines_index/pipelines'; +import Store from '~/vue_pipelines_index/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(); + 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('.js-pipelines-empty-state')).toBeDefined(); + 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(); + done(); + }); + }); + }); +}); |