diff options
author | Filipa Lacerda <filipa@gitlab.com> | 2018-08-07 18:06:38 +0300 |
---|---|---|
committer | Filipa Lacerda <filipa@gitlab.com> | 2018-08-07 18:06:38 +0300 |
commit | bcdc6f31195f176c6256c2960e6b87e56b62b522 (patch) | |
tree | d48daf07ceb830ab4deca120ee51893f88cede05 /spec/javascripts/reports | |
parent | bf699ff49860aa186dc485a91f9b04081b346549 (diff) |
Moves report components to reports folder
Diffstat (limited to 'spec/javascripts/reports')
4 files changed, 350 insertions, 0 deletions
diff --git a/spec/javascripts/reports/components/modal_open_name_spec.js b/spec/javascripts/reports/components/modal_open_name_spec.js new file mode 100644 index 00000000000..b18b3ef03d1 --- /dev/null +++ b/spec/javascripts/reports/components/modal_open_name_spec.js @@ -0,0 +1,45 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import component from '~/reports/components/modal_open_name.vue'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; + +describe('Modal open name', () => { + const Component = Vue.extend(component); + let vm; + + const store = new Vuex.Store({ + actions: { + openModal: () => {}, + }, + state: {}, + mutations: {}, + }); + + beforeEach(() => { + vm = mountComponentWithStore(Component, { + store, + props: { + issue: { + title: 'Issue', + }, + status: 'failed', + }, + }); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders the issue name', () => { + expect(vm.$el.textContent.trim()).toEqual('Issue'); + }); + + it('calls openModal actions when button is clicked', () => { + spyOn(vm, 'openModal'); + + vm.$el.click(); + + expect(vm.openModal).toHaveBeenCalled(); + }); +}); diff --git a/spec/javascripts/reports/components/report_link_spec.js b/spec/javascripts/reports/components/report_link_spec.js new file mode 100644 index 00000000000..cd6911e2f59 --- /dev/null +++ b/spec/javascripts/reports/components/report_link_spec.js @@ -0,0 +1,71 @@ +import Vue from 'vue'; +import component from '~/reports/components/report_link.vue'; +import mountComponent from '../../helpers/vue_mount_component_helper'; + +describe('report link', () => { + let vm; + + const Component = Vue.extend(component); + + afterEach(() => { + vm.$destroy(); + }); + + describe('With url', () => { + it('renders link', () => { + vm = mountComponent(Component, { + issue: { + path: 'Gemfile.lock', + urlPath: '/Gemfile.lock', + }, + }); + + expect(vm.$el.textContent.trim()).toContain('in'); + expect(vm.$el.querySelector('a').getAttribute('href')).toEqual('/Gemfile.lock'); + expect(vm.$el.querySelector('a').textContent.trim()).toEqual('Gemfile.lock'); + }); + }); + + describe('Without url', () => { + it('does not render link', () => { + vm = mountComponent(Component, { + issue: { + path: 'Gemfile.lock', + }, + }); + + expect(vm.$el.querySelector('a')).toBeNull(); + expect(vm.$el.textContent.trim()).toContain('in'); + expect(vm.$el.textContent.trim()).toContain('Gemfile.lock'); + }); + }); + + describe('with line', () => { + it('renders line number', () => { + vm = mountComponent(Component, { + issue: { + path: 'Gemfile.lock', + urlPath: + 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00', + line: 22, + }, + }); + + expect(vm.$el.querySelector('a').textContent.trim()).toContain('Gemfile.lock:22'); + }); + }); + + describe('without line', () => { + it('does not render line number', () => { + vm = mountComponent(Component, { + issue: { + path: 'Gemfile.lock', + urlPath: + 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00', + }, + }); + + expect(vm.$el.querySelector('a').textContent.trim()).not.toContain(':22'); + }); + }); +}); diff --git a/spec/javascripts/reports/components/report_section_spec.js b/spec/javascripts/reports/components/report_section_spec.js new file mode 100644 index 00000000000..6f6eb161d14 --- /dev/null +++ b/spec/javascripts/reports/components/report_section_spec.js @@ -0,0 +1,197 @@ +import Vue from 'vue'; +import reportSection from '~/reports/components/report_section.vue'; +import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper'; + +describe('Report section', () => { + let vm; + const ReportSection = Vue.extend(reportSection); + + const resolvedIssues = [ + { + name: 'Insecure Dependency', + fingerprint: 'ca2e59451e98ae60ba2f54e3857c50e5', + path: 'Gemfile.lock', + line: 12, + urlPath: 'foo/Gemfile.lock', + }, + ]; + + afterEach(() => { + vm.$destroy(); + }); + + describe('computed', () => { + beforeEach(() => { + vm = mountComponent(ReportSection, { + component: '', + status: 'SUCCESS', + loadingText: 'Loading codeclimate report', + errorText: 'foo', + successText: 'Code quality improved on 1 point and degraded on 1 point', + resolvedIssues, + hasIssues: false, + alwaysOpen: false, + }); + }); + + describe('isCollapsible', () => { + const testMatrix = [ + { hasIssues: false, alwaysOpen: false, isCollapsible: false }, + { hasIssues: false, alwaysOpen: true, isCollapsible: false }, + { hasIssues: true, alwaysOpen: false, isCollapsible: true }, + { hasIssues: true, alwaysOpen: true, isCollapsible: false }, + ]; + + testMatrix.forEach(({ hasIssues, alwaysOpen, isCollapsible }) => { + const issues = hasIssues ? 'has issues' : 'has no issues'; + const open = alwaysOpen ? 'is always open' : 'is not always open'; + + it(`is ${isCollapsible}, if the report ${issues} and ${open}`, done => { + vm.hasIssues = hasIssues; + vm.alwaysOpen = alwaysOpen; + + Vue.nextTick() + .then(() => { + expect(vm.isCollapsible).toBe(isCollapsible); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + + describe('isExpanded', () => { + const testMatrix = [ + { isCollapsed: false, alwaysOpen: false, isExpanded: true }, + { isCollapsed: false, alwaysOpen: true, isExpanded: true }, + { isCollapsed: true, alwaysOpen: false, isExpanded: false }, + { isCollapsed: true, alwaysOpen: true, isExpanded: true }, + ]; + + testMatrix.forEach(({ isCollapsed, alwaysOpen, isExpanded }) => { + const issues = isCollapsed ? 'is collapsed' : 'is not collapsed'; + const open = alwaysOpen ? 'is always open' : 'is not always open'; + + it(`is ${isExpanded}, if the report ${issues} and ${open}`, done => { + vm.isCollapsed = isCollapsed; + vm.alwaysOpen = alwaysOpen; + + Vue.nextTick() + .then(() => { + expect(vm.isExpanded).toBe(isExpanded); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + }); + describe('when it is loading', () => { + it('should render loading indicator', () => { + vm = mountComponent(ReportSection, { + component: '', + status: 'LOADING', + loadingText: 'Loading codeclimate report', + errorText: 'foo', + successText: 'Code quality improved on 1 point and degraded on 1 point', + hasIssues: false, + }); + expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report'); + }); + }); + + describe('with success status', () => { + beforeEach(() => { + vm = mountComponent(ReportSection, { + component: '', + status: 'SUCCESS', + loadingText: 'Loading codeclimate report', + errorText: 'foo', + successText: 'Code quality improved on 1 point and degraded on 1 point', + resolvedIssues, + hasIssues: true, + }); + }); + + it('should render provided data', () => { + expect(vm.$el.querySelector('.js-code-text').textContent.trim()).toEqual( + 'Code quality improved on 1 point and degraded on 1 point', + ); + + expect(vm.$el.querySelectorAll('.js-mr-code-resolved-issues li').length).toEqual( + resolvedIssues.length, + ); + }); + + describe('toggleCollapsed', () => { + const hiddenCss = { display: 'none' }; + + it('toggles issues', done => { + vm.$el.querySelector('button').click(); + + Vue.nextTick() + .then(() => { + expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss); + expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Collapse'); + + vm.$el.querySelector('button').click(); + }) + .then(Vue.nextTick) + .then(() => { + expect(vm.$el.querySelector('.js-report-section-container')).toHaveCss(hiddenCss); + expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Expand'); + }) + .then(done) + .catch(done.fail); + }); + + it('is always expanded, if always-open is set to true', done => { + vm.alwaysOpen = true; + Vue.nextTick() + .then(() => { + expect(vm.$el.querySelector('.js-report-section-container')).not.toHaveCss(hiddenCss); + expect(vm.$el.querySelector('button')).toBeNull(); + }) + .then(done) + .catch(done.fail); + }); + }); + }); + + describe('with failed request', () => { + it('should render error indicator', () => { + vm = mountComponent(ReportSection, { + component: '', + status: 'ERROR', + loadingText: 'Loading codeclimate report', + errorText: 'Failed to load codeclimate report', + successText: 'Code quality improved on 1 point and degraded on 1 point', + hasIssues: false, + }); + expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report'); + }); + }); + + describe('with action buttons passed to the slot', () => { + beforeEach(() => { + vm = mountComponentWithSlots(ReportSection, { + props: { + status: 'SUCCESS', + successText: 'success', + hasIssues: true, + }, + slots: { + actionButtons: ['Action!'], + }, + }); + }); + + it('should render the passed button', () => { + expect(vm.$el.textContent.trim()).toContain('Action!'); + }); + + it('should still render the expand/collapse button', () => { + expect(vm.$el.querySelector('.js-collapse-btn').textContent.trim()).toEqual('Expand'); + }); + }); +}); diff --git a/spec/javascripts/reports/components/summary_row_spec.js b/spec/javascripts/reports/components/summary_row_spec.js new file mode 100644 index 00000000000..fab7693581c --- /dev/null +++ b/spec/javascripts/reports/components/summary_row_spec.js @@ -0,0 +1,37 @@ +import Vue from 'vue'; +import component from '~/reports/components/summary_row.vue'; +import mountComponent from 'spec/helpers/vue_mount_component_helper'; + +describe('Summary row', () => { + const Component = Vue.extend(component); + let vm; + + const props = { + summary: 'SAST detected 1 new vulnerability and 1 fixed vulnerability', + popoverOptions: { + title: 'Static Application Security Testing (SAST)', + content: '<a>Learn more about SAST</a>', + }, + statusIcon: 'warning', + }; + + beforeEach(() => { + vm = mountComponent(Component, props); + }); + + afterEach(() => { + vm.$destroy(); + }); + + it('renders provided summary', () => { + expect( + vm.$el.querySelector('.report-block-list-issue-description-text').textContent.trim(), + ).toEqual(props.summary); + }); + + it('renders provided icon', () => { + expect(vm.$el.querySelector('.report-block-list-icon span').classList).toContain( + 'js-ci-status-icon-warning', + ); + }); +}); |