diff options
Diffstat (limited to 'spec/javascripts')
12 files changed, 104 insertions, 940 deletions
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js index e5d1d1d690e..d0b54a16747 100644 --- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js +++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js @@ -8,6 +8,7 @@ import FilteredSearchVisualTokens from '~/filtered_search/filtered_search_visual import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dropdown_manager'; import FilteredSearchManager from '~/filtered_search/filtered_search_manager'; import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper'; +import { BACKSPACE_KEY_CODE, DELETE_KEY_CODE } from '~/lib/utils/keycodes'; describe('Filtered Search Manager', function() { let input; @@ -17,16 +18,35 @@ describe('Filtered Search Manager', function() { const placeholder = 'Search or filter results...'; function dispatchBackspaceEvent(element, eventType) { - const backspaceKey = 8; const event = new Event(eventType); - event.keyCode = backspaceKey; + event.keyCode = BACKSPACE_KEY_CODE; element.dispatchEvent(event); } function dispatchDeleteEvent(element, eventType) { - const deleteKey = 46; const event = new Event(eventType); - event.keyCode = deleteKey; + event.keyCode = DELETE_KEY_CODE; + element.dispatchEvent(event); + } + + function dispatchAltBackspaceEvent(element, eventType) { + const event = new Event(eventType); + event.altKey = true; + event.keyCode = BACKSPACE_KEY_CODE; + element.dispatchEvent(event); + } + + function dispatchCtrlBackspaceEvent(element, eventType) { + const event = new Event(eventType); + event.ctrlKey = true; + event.keyCode = BACKSPACE_KEY_CODE; + element.dispatchEvent(event); + } + + function dispatchMetaBackspaceEvent(element, eventType) { + const event = new Event(eventType); + event.metaKey = true; + event.keyCode = BACKSPACE_KEY_CODE; element.dispatchEvent(event); } @@ -299,6 +319,80 @@ describe('Filtered Search Manager', function() { }); }); + describe('checkForAltOrCtrlBackspace', () => { + beforeEach(() => { + initializeManager(); + spyOn(FilteredSearchVisualTokens, 'removeLastTokenPartial').and.callThrough(); + }); + + describe('tokens and no input', () => { + beforeEach(() => { + tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( + FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'), + ); + }); + + it('removes last token via alt-backspace', () => { + dispatchAltBackspaceEvent(input, 'keydown'); + + expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled(); + }); + + it('removes last token via ctrl-backspace', () => { + dispatchCtrlBackspaceEvent(input, 'keydown'); + + expect(FilteredSearchVisualTokens.removeLastTokenPartial).toHaveBeenCalled(); + }); + }); + + describe('tokens and input', () => { + beforeEach(() => { + tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( + FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'), + ); + }); + + it('does not remove token or change input via alt-backspace when there is existing input', () => { + input = manager.filteredSearchInput; + input.value = 'text'; + dispatchAltBackspaceEvent(input, 'keydown'); + + expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled(); + expect(input.value).toEqual('text'); + }); + + it('does not remove token or change input via ctrl-backspace when there is existing input', () => { + input = manager.filteredSearchInput; + input.value = 'text'; + dispatchCtrlBackspaceEvent(input, 'keydown'); + + expect(FilteredSearchVisualTokens.removeLastTokenPartial).not.toHaveBeenCalled(); + expect(input.value).toEqual('text'); + }); + }); + }); + + describe('checkForMetaBackspace', () => { + beforeEach(() => { + initializeManager(); + }); + + beforeEach(() => { + tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML( + FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '=', '~bug'), + ); + }); + + it('removes all tokens and input', () => { + spyOn(FilteredSearchManager.prototype, 'clearSearch').and.callThrough(); + dispatchMetaBackspaceEvent(input, 'keydown'); + + expect(manager.clearSearch).toHaveBeenCalled(); + expect(manager.filteredSearchInput.value).toEqual(''); + expect(DropdownUtils.getSearchQuery()).toEqual(''); + }); + }); + describe('removeToken', () => { beforeEach(() => { initializeManager(); diff --git a/spec/javascripts/monitoring/components/dashboard_resize_spec.js b/spec/javascripts/monitoring/components/dashboard_resize_spec.js index 6455346e890..0c3193940e6 100644 --- a/spec/javascripts/monitoring/components/dashboard_resize_spec.js +++ b/spec/javascripts/monitoring/components/dashboard_resize_spec.js @@ -2,66 +2,13 @@ import Vue from 'vue'; import { createLocalVue } from '@vue/test-utils'; import MockAdapter from 'axios-mock-adapter'; import Dashboard from '~/monitoring/components/dashboard.vue'; -import * as types from '~/monitoring/stores/mutation_types'; import { createStore } from '~/monitoring/stores'; import axios from '~/lib/utils/axios_utils'; -import { - metricsDashboardPayload, - mockedEmptyResult, - mockedQueryResultPayload, - mockedQueryResultPayloadCoresTotal, - mockApiEndpoint, - environmentData, -} from '../mock_data'; +import { mockApiEndpoint, propsData } from '../mock_data'; +import { metricsDashboardPayload } from '../fixture_data'; +import { setupStoreWithData } from '../store_utils'; const localVue = createLocalVue(); -const propsData = { - hasMetrics: false, - documentationPath: '/path/to/docs', - settingsPath: '/path/to/settings', - clustersPath: '/path/to/clusters', - tagsPath: '/path/to/tags', - projectPath: '/path/to/project', - defaultBranch: 'master', - metricsEndpoint: mockApiEndpoint, - deploymentsEndpoint: null, - emptyGettingStartedSvgPath: '/path/to/getting-started.svg', - emptyLoadingSvgPath: '/path/to/loading.svg', - emptyNoDataSvgPath: '/path/to/no-data.svg', - emptyNoDataSmallSvgPath: '/path/to/no-data-small.svg', - emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg', - currentEnvironmentName: 'production', - customMetricsAvailable: false, - customMetricsPath: '', - validateQueryPath: '', -}; - -function setupComponentStore(component) { - // Load 2 panel groups - component.$store.commit( - `monitoringDashboard/${types.RECEIVE_METRICS_DASHBOARD_SUCCESS}`, - metricsDashboardPayload, - ); - - // Load 3 panels to the dashboard, one with an empty result - component.$store.commit( - `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, - mockedEmptyResult, - ); - component.$store.commit( - `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, - mockedQueryResultPayload, - ); - component.$store.commit( - `monitoringDashboard/${types.RECEIVE_METRIC_RESULT_SUCCESS}`, - mockedQueryResultPayloadCoresTotal, - ); - - component.$store.commit( - `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, - environmentData, - ); -} describe('Dashboard', () => { let DashboardComponent; @@ -109,7 +56,7 @@ describe('Dashboard', () => { store, }); - setupComponentStore(component); + setupStoreWithData(component.$store); return Vue.nextTick().then(() => { [promPanel] = component.$el.querySelectorAll('.prometheus-panel'); diff --git a/spec/javascripts/monitoring/fixture_data.js b/spec/javascripts/monitoring/fixture_data.js new file mode 100644 index 00000000000..1375c27cdde --- /dev/null +++ b/spec/javascripts/monitoring/fixture_data.js @@ -0,0 +1 @@ +export * from '../../frontend/monitoring/fixture_data'; diff --git a/spec/javascripts/monitoring/store_utils.js b/spec/javascripts/monitoring/store_utils.js new file mode 100644 index 00000000000..1222716c829 --- /dev/null +++ b/spec/javascripts/monitoring/store_utils.js @@ -0,0 +1 @@ +export * from '../../frontend/monitoring/store_utils'; diff --git a/spec/javascripts/pipelines/graph/graph_component_spec.js b/spec/javascripts/pipelines/graph/graph_component_spec.js deleted file mode 100644 index d2c10362ba3..00000000000 --- a/spec/javascripts/pipelines/graph/graph_component_spec.js +++ /dev/null @@ -1,274 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import PipelineStore from '~/pipelines/stores/pipeline_store'; -import graphComponent from '~/pipelines/components/graph/graph_component.vue'; -import graphJSON from './mock_data'; -import linkedPipelineJSON from '../linked_pipelines_mock.json'; -import PipelinesMediator from '~/pipelines/pipeline_details_mediator'; - -describe('graph component', () => { - const GraphComponent = Vue.extend(graphComponent); - const store = new PipelineStore(); - store.storePipeline(linkedPipelineJSON); - const mediator = new PipelinesMediator({ endpoint: '' }); - - let component; - - beforeEach(() => { - setFixtures(` - <div class="layout-page"></div> - `); - }); - - afterEach(() => { - component.$destroy(); - }); - - describe('while is loading', () => { - it('should render a loading icon', () => { - component = mountComponent(GraphComponent, { - isLoading: true, - pipeline: {}, - mediator, - }); - - expect(component.$el.querySelector('.loading-icon')).toBeDefined(); - }); - }); - - describe('with data', () => { - it('should render the graph', () => { - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: graphJSON, - mediator, - }); - - expect(component.$el.classList.contains('js-pipeline-graph')).toEqual(true); - - expect( - component.$el.querySelector('.stage-column:first-child').classList.contains('no-margin'), - ).toEqual(true); - - expect( - component.$el.querySelector('.stage-column:nth-child(2)').classList.contains('left-margin'), - ).toEqual(true); - - expect( - component.$el - .querySelector('.stage-column:nth-child(2) .build:nth-child(1)') - .classList.contains('left-connector'), - ).toEqual(true); - - expect(component.$el.querySelector('loading-icon')).toBe(null); - - expect(component.$el.querySelector('.stage-column-list')).toBeDefined(); - }); - }); - - describe('when linked pipelines are present', () => { - beforeEach(() => { - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: store.state.pipeline, - mediator, - }); - }); - - describe('rendered output', () => { - it('should include the pipelines graph', () => { - expect(component.$el.classList.contains('js-pipeline-graph')).toEqual(true); - }); - - it('should not include the loading icon', () => { - expect(component.$el.querySelector('.fa-spinner')).toBeNull(); - }); - - it('should include the stage column list', () => { - expect(component.$el.querySelector('.stage-column-list')).not.toBeNull(); - }); - - it('should include the no-margin class on the first child', () => { - const firstStageColumnElement = component.$el.querySelector( - '.stage-column-list .stage-column', - ); - - expect(firstStageColumnElement.classList.contains('no-margin')).toEqual(true); - }); - - it('should include the has-only-one-job class on the first child', () => { - const firstStageColumnElement = component.$el.querySelector( - '.stage-column-list .stage-column', - ); - - expect(firstStageColumnElement.classList.contains('has-only-one-job')).toEqual(true); - }); - - it('should include the left-margin class on the second child', () => { - const firstStageColumnElement = component.$el.querySelector( - '.stage-column-list .stage-column:last-child', - ); - - expect(firstStageColumnElement.classList.contains('left-margin')).toEqual(true); - }); - - it('should include the js-has-linked-pipelines flag', () => { - expect(component.$el.querySelector('.js-has-linked-pipelines')).not.toBeNull(); - }); - }); - - describe('computeds and methods', () => { - describe('capitalizeStageName', () => { - it('it capitalizes the stage name', () => { - expect(component.capitalizeStageName('mystage')).toBe('Mystage'); - }); - }); - - describe('stageConnectorClass', () => { - it('it returns left-margin when there is a triggerer', () => { - expect(component.stageConnectorClass(0, { groups: ['job'] })).toBe('no-margin'); - }); - }); - }); - - describe('linked pipelines components', () => { - beforeEach(() => { - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: store.state.pipeline, - mediator, - }); - }); - - it('should render an upstream pipelines column', () => { - expect(component.$el.querySelector('.linked-pipelines-column')).not.toBeNull(); - expect(component.$el.innerHTML).toContain('Upstream'); - }); - - it('should render a downstream pipelines column', () => { - expect(component.$el.querySelector('.linked-pipelines-column')).not.toBeNull(); - expect(component.$el.innerHTML).toContain('Downstream'); - }); - - describe('triggered by', () => { - describe('on click', () => { - it('should emit `onClickTriggeredBy` when triggered by linked pipeline is clicked', () => { - spyOn(component, '$emit'); - - component.$el.querySelector('#js-linked-pipeline-12').click(); - - expect(component.$emit).toHaveBeenCalledWith( - 'onClickTriggeredBy', - component.pipeline.triggered_by[0], - ); - }); - }); - - describe('with expanded pipeline', () => { - it('should render expanded pipeline', done => { - // expand the pipeline - store.state.pipeline.triggered_by[0].isExpanded = true; - - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: store.state.pipeline, - mediator, - }); - - Vue.nextTick() - .then(() => { - expect(component.$el.querySelector('.js-upstream-pipeline-12')).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); - }); - }); - - describe('triggered', () => { - describe('on click', () => { - it('should emit `onClickTriggered`', () => { - spyOn(component, '$emit'); - spyOn(component, 'calculateMarginTop').and.callFake(() => '16px'); - - component.$el.querySelector('#js-linked-pipeline-34993051').click(); - - expect(component.$emit).toHaveBeenCalledWith( - 'onClickTriggered', - component.pipeline.triggered[0], - ); - }); - }); - - describe('with expanded pipeline', () => { - it('should render expanded pipeline', done => { - // expand the pipeline - store.state.pipeline.triggered[0].isExpanded = true; - - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: store.state.pipeline, - mediator, - }); - - Vue.nextTick() - .then(() => { - expect( - component.$el.querySelector('.js-downstream-pipeline-34993051'), - ).not.toBeNull(); - }) - .then(done) - .catch(done.fail); - }); - }); - }); - }); - }); - - describe('when linked pipelines are not present', () => { - beforeEach(() => { - const pipeline = Object.assign(linkedPipelineJSON, { triggered: null, triggered_by: null }); - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline, - mediator, - }); - }); - - describe('rendered output', () => { - it('should include the first column with a no margin', () => { - const firstColumn = component.$el.querySelector('.stage-column:first-child'); - - expect(firstColumn.classList.contains('no-margin')).toEqual(true); - }); - - it('should not render a linked pipelines column', () => { - expect(component.$el.querySelector('.linked-pipelines-column')).toBeNull(); - }); - }); - - describe('stageConnectorClass', () => { - it('it returns left-margin when no triggerer and there is one job', () => { - expect(component.stageConnectorClass(0, { groups: ['job'] })).toBe('no-margin'); - }); - - it('it returns left-margin when no triggerer and not the first stage', () => { - expect(component.stageConnectorClass(99, { groups: ['job'] })).toBe('left-margin'); - }); - }); - }); - - describe('capitalizeStageName', () => { - it('capitalizes and escapes stage name', () => { - component = mountComponent(GraphComponent, { - isLoading: false, - pipeline: graphJSON, - mediator, - }); - - expect( - component.$el.querySelector('.stage-column:nth-child(2) .stage-name').textContent.trim(), - ).toEqual('Deploy <img src=x onerror=alert(document.domain)>'); - }); - }); -}); diff --git a/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js deleted file mode 100644 index a3957f94caa..00000000000 --- a/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js +++ /dev/null @@ -1,85 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue'; - -describe('job group dropdown component', () => { - const Component = Vue.extend(JobGroupDropdown); - let vm; - - const group = { - jobs: [ - { - id: 4256, - name: '<img src=x onerror=alert(document.domain)>', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - tooltip: 'passed', - group: 'success', - details_path: '/root/ci-mock/builds/4256', - has_details: true, - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4256/retry', - method: 'post', - }, - }, - }, - { - id: 4299, - name: 'test', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - tooltip: 'passed', - group: 'success', - details_path: '/root/ci-mock/builds/4299', - has_details: true, - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4299/retry', - method: 'post', - }, - }, - }, - ], - name: 'rspec:linux', - size: 2, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - tooltip: 'passed', - group: 'success', - details_path: '/root/ci-mock/builds/4256', - has_details: true, - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4256/retry', - method: 'post', - }, - }, - }; - - afterEach(() => { - vm.$destroy(); - }); - - beforeEach(() => { - vm = mountComponent(Component, { group }); - }); - - it('renders button with group name and size', () => { - expect(vm.$el.querySelector('button').textContent).toContain(group.name); - expect(vm.$el.querySelector('button').textContent).toContain(group.size); - }); - - it('renders dropdown with jobs', () => { - expect(vm.$el.querySelectorAll('.scrollable-menu>ul>li').length).toEqual(group.jobs.length); - }); -}); diff --git a/spec/javascripts/pipelines/graph/job_name_component_spec.js b/spec/javascripts/pipelines/graph/job_name_component_spec.js deleted file mode 100644 index c861d452dd0..00000000000 --- a/spec/javascripts/pipelines/graph/job_name_component_spec.js +++ /dev/null @@ -1,27 +0,0 @@ -import Vue from 'vue'; -import jobNameComponent from '~/pipelines/components/graph/job_name_component.vue'; - -describe('job name component', () => { - let component; - - beforeEach(() => { - const JobNameComponent = Vue.extend(jobNameComponent); - component = new JobNameComponent({ - propsData: { - name: 'foo', - status: { - icon: 'status_success', - }, - }, - }).$mount(); - }); - - it('should render the provided name', () => { - expect(component.$el.querySelector('.ci-status-text').textContent.trim()).toEqual('foo'); - }); - - it('should render an icon with the provided status', () => { - expect(component.$el.querySelector('.ci-status-icon-success')).toBeDefined(); - expect(component.$el.querySelector('.ci-status-icon-success svg')).toBeDefined(); - }); -}); diff --git a/spec/javascripts/pipelines/graph/linked_pipelines_column_spec.js b/spec/javascripts/pipelines/graph/linked_pipelines_column_spec.js deleted file mode 100644 index 613ab2a906f..00000000000 --- a/spec/javascripts/pipelines/graph/linked_pipelines_column_spec.js +++ /dev/null @@ -1,43 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import LinkedPipelinesColumn from '~/pipelines/components/graph/linked_pipelines_column.vue'; -import mockData from './linked_pipelines_mock_data'; - -describe('Linked Pipelines Column', () => { - const Component = Vue.extend(LinkedPipelinesColumn); - const props = { - columnTitle: 'Upstream', - linkedPipelines: mockData.triggered, - graphPosition: 'right', - projectId: 19, - }; - let vm; - - beforeEach(() => { - vm = mountComponent(Component, props); - }); - - afterEach(() => { - vm.$destroy(); - }); - - it('renders the pipeline orientation', () => { - const titleElement = vm.$el.querySelector('.linked-pipelines-column-title'); - - expect(titleElement.innerText).toContain(props.columnTitle); - }); - - it('has the correct number of linked pipeline child components', () => { - expect(vm.$children.length).toBe(props.linkedPipelines.length); - }); - - it('renders the correct number of linked pipelines', () => { - const linkedPipelineElements = vm.$el.querySelectorAll('.linked-pipeline'); - - expect(linkedPipelineElements.length).toBe(props.linkedPipelines.length); - }); - - it('renders cross project triangle when column is upstream', () => { - expect(vm.$el.querySelector('.cross-project-triangle')).toBeDefined(); - }); -}); diff --git a/spec/javascripts/pipelines/graph/linked_pipelines_mock_data.js b/spec/javascripts/pipelines/graph/linked_pipelines_mock_data.js deleted file mode 100644 index 3079d5e4e68..00000000000 --- a/spec/javascripts/pipelines/graph/linked_pipelines_mock_data.js +++ /dev/null @@ -1,3 +0,0 @@ -import mockData from '../../../frontend/pipelines/graph/linked_pipelines_mock_data'; - -export default mockData; diff --git a/spec/javascripts/pipelines/graph/mock_data.js b/spec/javascripts/pipelines/graph/mock_data.js deleted file mode 100644 index a4a5d78f906..00000000000 --- a/spec/javascripts/pipelines/graph/mock_data.js +++ /dev/null @@ -1,261 +0,0 @@ -export default { - id: 123, - user: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: null, - web_url: 'http://localhost:3000/root', - }, - active: false, - coverage: null, - path: '/root/ci-mock/pipelines/123', - details: { - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/pipelines/123', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - }, - duration: 9, - finished_at: '2017-04-19T14:30:27.542Z', - stages: [ - { - name: 'test', - title: 'test: passed', - groups: [ - { - name: 'test', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4153', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4153/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 4153, - name: 'test', - build_path: '/root/ci-mock/builds/4153', - retry_path: '/root/ci-mock/builds/4153/retry', - playable: false, - created_at: '2017-04-13T09:25:18.959Z', - updated_at: '2017-04-13T09:25:23.118Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4153', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4153/retry', - method: 'post', - }, - }, - }, - ], - }, - ], - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/pipelines/123#test', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - }, - path: '/root/ci-mock/pipelines/123#test', - dropdown_path: '/root/ci-mock/pipelines/123/stage.json?stage=test', - }, - { - name: 'deploy <img src=x onerror=alert(document.domain)>', - title: 'deploy: passed', - groups: [ - { - name: 'deploy to production', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4166', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4166/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 4166, - name: 'deploy to production', - build_path: '/root/ci-mock/builds/4166', - retry_path: '/root/ci-mock/builds/4166/retry', - playable: false, - created_at: '2017-04-19T14:29:46.463Z', - updated_at: '2017-04-19T14:30:27.498Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4166', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4166/retry', - method: 'post', - }, - }, - }, - ], - }, - { - name: 'deploy to staging', - size: 1, - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4159', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4159/retry', - method: 'post', - }, - }, - jobs: [ - { - id: 4159, - name: 'deploy to staging', - build_path: '/root/ci-mock/builds/4159', - retry_path: '/root/ci-mock/builds/4159/retry', - playable: false, - created_at: '2017-04-18T16:32:08.420Z', - updated_at: '2017-04-18T16:32:12.631Z', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/builds/4159', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4159/retry', - method: 'post', - }, - }, - }, - ], - }, - ], - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - has_details: true, - details_path: '/root/ci-mock/pipelines/123#deploy', - favicon: - '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png', - }, - path: '/root/ci-mock/pipelines/123#deploy', - dropdown_path: '/root/ci-mock/pipelines/123/stage.json?stage=deploy', - }, - ], - artifacts: [], - manual_actions: [ - { - name: 'deploy to production', - path: '/root/ci-mock/builds/4166/play', - playable: false, - }, - ], - }, - flags: { - latest: true, - triggered: false, - stuck: false, - yaml_errors: false, - retryable: false, - cancelable: false, - }, - ref: { - name: 'master', - path: '/root/ci-mock/tree/master', - tag: false, - branch: true, - }, - commit: { - id: '798e5f902592192afaba73f4668ae30e56eae492', - short_id: '798e5f90', - title: "Merge branch 'new-branch' into 'master'\r", - created_at: '2017-04-13T10:25:17.000+01:00', - parent_ids: [ - '54d483b1ed156fbbf618886ddf7ab023e24f8738', - 'c8e2d38a6c538822e81c57022a6e3a0cfedebbcc', - ], - message: - "Merge branch 'new-branch' into 'master'\r\n\r\nAdd new file\r\n\r\nSee merge request !1", - author_name: 'Root', - author_email: 'admin@example.com', - authored_date: '2017-04-13T10:25:17.000+01:00', - committer_name: 'Root', - committer_email: 'admin@example.com', - committed_date: '2017-04-13T10:25:17.000+01:00', - author: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: null, - web_url: 'http://localhost:3000/root', - }, - author_gravatar_url: null, - commit_url: - 'http://localhost:3000/root/ci-mock/commit/798e5f902592192afaba73f4668ae30e56eae492', - commit_path: '/root/ci-mock/commit/798e5f902592192afaba73f4668ae30e56eae492', - }, - created_at: '2017-04-13T09:25:18.881Z', - updated_at: '2017-04-19T14:30:27.561Z', -}; diff --git a/spec/javascripts/pipelines/graph/stage_column_component_spec.js b/spec/javascripts/pipelines/graph/stage_column_component_spec.js deleted file mode 100644 index dbfeeae43fe..00000000000 --- a/spec/javascripts/pipelines/graph/stage_column_component_spec.js +++ /dev/null @@ -1,122 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import stageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue'; - -describe('stage column component', () => { - let component; - const StageColumnComponent = Vue.extend(stageColumnComponent); - - const mockJob = { - id: 4250, - name: 'test', - status: { - icon: 'status_success', - text: 'passed', - label: 'passed', - group: 'success', - details_path: '/root/ci-mock/builds/4250', - action: { - icon: 'retry', - title: 'Retry', - path: '/root/ci-mock/builds/4250/retry', - method: 'post', - }, - }, - }; - - beforeEach(() => { - const mockGroups = []; - for (let i = 0; i < 3; i += 1) { - const mockedJob = Object.assign({}, mockJob); - mockedJob.id += i; - mockGroups.push(mockedJob); - } - - component = mountComponent(StageColumnComponent, { - title: 'foo', - groups: mockGroups, - hasTriggeredBy: false, - }); - }); - - it('should render provided title', () => { - expect(component.$el.querySelector('.stage-name').textContent.trim()).toEqual('foo'); - }); - - it('should render the provided groups', () => { - expect(component.$el.querySelectorAll('.builds-container > ul > li').length).toEqual(3); - }); - - describe('jobId', () => { - it('escapes job name', () => { - component = mountComponent(StageColumnComponent, { - groups: [ - { - id: 4259, - name: '<img src=x onerror=alert(document.domain)>', - status: { - icon: 'status_success', - label: 'success', - tooltip: '<img src=x onerror=alert(document.domain)>', - }, - }, - ], - title: 'test', - hasTriggeredBy: false, - }); - - expect(component.$el.querySelector('.builds-container li').getAttribute('id')).toEqual( - 'ci-badge-<img src=x onerror=alert(document.domain)>', - ); - }); - }); - - describe('with action', () => { - it('renders action button', () => { - component = mountComponent(StageColumnComponent, { - groups: [ - { - id: 4259, - name: '<img src=x onerror=alert(document.domain)>', - status: { - icon: 'status_success', - label: 'success', - tooltip: '<img src=x onerror=alert(document.domain)>', - }, - }, - ], - title: 'test', - hasTriggeredBy: false, - action: { - icon: 'play', - title: 'Play all', - path: 'action', - }, - }); - - expect(component.$el.querySelector('.js-stage-action')).not.toBeNull(); - }); - }); - - describe('without action', () => { - it('does not render action button', () => { - component = mountComponent(StageColumnComponent, { - groups: [ - { - id: 4259, - name: '<img src=x onerror=alert(document.domain)>', - status: { - icon: 'status_success', - label: 'success', - tooltip: '<img src=x onerror=alert(document.domain)>', - }, - }, - ], - title: 'test', - hasTriggeredBy: false, - }); - - expect(component.$el.querySelector('.js-stage-action')).toBeNull(); - }); - }); -}); diff --git a/spec/javascripts/sidebar/sidebar_assignees_spec.js b/spec/javascripts/sidebar/sidebar_assignees_spec.js deleted file mode 100644 index 23b8dc69925..00000000000 --- a/spec/javascripts/sidebar/sidebar_assignees_spec.js +++ /dev/null @@ -1,64 +0,0 @@ -import Vue from 'vue'; -import mountComponent from 'spec/helpers/vue_mount_component_helper'; -import SidebarAssignees from '~/sidebar/components/assignees/sidebar_assignees.vue'; -import SidebarMediator from '~/sidebar/sidebar_mediator'; -import SidebarService from '~/sidebar/services/sidebar_service'; -import SidebarStore from '~/sidebar/stores/sidebar_store'; -import Mock from './mock_data'; - -describe('sidebar assignees', () => { - let vm; - let mediator; - let sidebarAssigneesEl; - preloadFixtures('issues/open-issue.html'); - - beforeEach(() => { - loadFixtures('issues/open-issue.html'); - - mediator = new SidebarMediator(Mock.mediator); - spyOn(mediator, 'saveAssignees').and.callThrough(); - spyOn(mediator, 'assignYourself').and.callThrough(); - - const SidebarAssigneeComponent = Vue.extend(SidebarAssignees); - sidebarAssigneesEl = document.querySelector('#js-vue-sidebar-assignees'); - vm = mountComponent( - SidebarAssigneeComponent, - { - mediator, - field: sidebarAssigneesEl.dataset.field, - }, - sidebarAssigneesEl, - ); - }); - - afterEach(() => { - SidebarService.singleton = null; - SidebarStore.singleton = null; - SidebarMediator.singleton = null; - }); - - it('calls the mediator when saves the assignees', () => { - vm.saveAssignees(); - - expect(mediator.saveAssignees).toHaveBeenCalled(); - }); - - it('calls the mediator when "assignSelf" method is called', () => { - vm.assignSelf(); - - expect(mediator.assignYourself).toHaveBeenCalled(); - expect(mediator.store.assignees.length).toEqual(1); - }); - - it('hides assignees until fetched', done => { - const currentAssignee = sidebarAssigneesEl.querySelector('.value'); - - expect(currentAssignee).toBe(null); - - vm.store.isFetching.assignees = false; - Vue.nextTick(() => { - expect(vm.$el.querySelector('.value')).toBeVisible(); - done(); - }); - }); -}); |