From 369124baf4d1fa0c5d573a4c630ae8358ac3560b Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 24 Apr 2017 16:34:16 +0100 Subject: [PATCH 1/6] Close dropdown when error is received for jQuert dropdown class. Fix scss to show arrow icon --- .../mini_pipeline_graph_dropdown.js | 5 +- app/assets/stylesheets/pages/pipelines.scss | 2 + .../mini_pipeline_graph_dropdown_spec.js | 106 ++++++++++-------- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js index 9c58c4650013b6..5036187d5c29f8 100644 --- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js +++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js @@ -28,7 +28,9 @@ export default class MiniPipelineGraph { * All dropdown events are fired at the .dropdown-menu's parent element. */ bindEvents() { - $(document).off('shown.bs.dropdown', this.container).on('shown.bs.dropdown', this.container, this.getBuildsList); + $(document) + .off('shown.bs.dropdown', this.container) + .on('shown.bs.dropdown', this.container, this.getBuildsList); } /** @@ -91,6 +93,7 @@ export default class MiniPipelineGraph { }, error: () => { this.toggleLoading(button); + $(button).dropdown('toggle'); new Flash('An error occurred while fetching the builds.', 'alert'); }, }); diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 39c57d982ab3b5..f3f32407636cf6 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -897,6 +897,8 @@ * Top arrow in the dropdown in the mini pipeline graph */ .mini-pipeline-graph-dropdown-menu { + overflow: visible; // Needed for the arrow to be visible. + .arrow-up { &::before, &::after { diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js index e504d41d4d4d5c..e8d4d129e06b11 100644 --- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js +++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js @@ -3,70 +3,84 @@ import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; import '~/flash'; -(() => { - describe('Mini Pipeline Graph Dropdown', () => { - preloadFixtures('static/mini_dropdown_graph.html.raw'); +describe('Mini Pipeline Graph Dropdown', () => { + preloadFixtures('static/mini_dropdown_graph.html.raw'); - beforeEach(() => { - loadFixtures('static/mini_dropdown_graph.html.raw'); - }); + beforeEach(() => { + loadFixtures('static/mini_dropdown_graph.html.raw'); + }); - describe('When is initialized', () => { - it('should initialize without errors when no options are given', () => { - const miniPipelineGraph = new MiniPipelineGraph(); + describe('When is initialized', () => { + it('should initialize without errors when no options are given', () => { + const miniPipelineGraph = new MiniPipelineGraph(); - expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container'); - }); + expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container'); + }); - it('should set the container as the given prop', () => { - const container = '.foo'; + it('should set the container as the given prop', () => { + const container = '.foo'; - const miniPipelineGraph = new MiniPipelineGraph({ container }); + const miniPipelineGraph = new MiniPipelineGraph({ container }); - expect(miniPipelineGraph.container).toEqual(container); - }); + expect(miniPipelineGraph.container).toEqual(container); }); + }); - describe('When dropdown is clicked', () => { - it('should call getBuildsList', () => { - const getBuildsListSpy = spyOn(MiniPipelineGraph.prototype, 'getBuildsList').and.callFake(function () {}); + describe('When dropdown is clicked', () => { + it('should call getBuildsList', () => { + const getBuildsListSpy = spyOn( + MiniPipelineGraph.prototype, + 'getBuildsList', + ).and.callFake(function () {}); - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); + new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - document.querySelector('.js-builds-dropdown-button').click(); + document.querySelector('.js-builds-dropdown-button').click(); - expect(getBuildsListSpy).toHaveBeenCalled(); - }); + expect(getBuildsListSpy).toHaveBeenCalled(); + }); - it('should make a request to the endpoint provided in the html', () => { - const ajaxSpy = spyOn($, 'ajax').and.callFake(function () {}); + it('should make a request to the endpoint provided in the html', () => { + const ajaxSpy = spyOn($, 'ajax').and.callFake(function () {}); - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); + new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - document.querySelector('.js-builds-dropdown-button').click(); - expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar'); - }); + document.querySelector('.js-builds-dropdown-button').click(); + expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar'); + }); - it('should not close when user uses cmd/ctrl + click', () => { - spyOn($, 'ajax').and.callFake(function (params) { - params.success({ - html: `
  • - - - build - - -
  • `, - }); + it('should not close when user uses cmd/ctrl + click', () => { + spyOn($, 'ajax').and.callFake(function (params) { + params.success({ + html: `
  • + + + build + + +
  • `, }); - new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); + }); + new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); - document.querySelector('.js-builds-dropdown-button').click(); + document.querySelector('.js-builds-dropdown-button').click(); - document.querySelector('a.mini-pipeline-graph-dropdown-item').click(); + document.querySelector('a.mini-pipeline-graph-dropdown-item').click(); - expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true); - }); + expect($('.js-builds-dropdown-list').is(':visible')).toEqual(true); }); }); -})(); + + it('should close the dropdown when request returns an error', (done) => { + spyOn($, 'ajax').and.callFake(options => options.error()); + + new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents(); + + document.querySelector('.js-builds-dropdown-button').click(); + + setTimeout(() => { + expect($('.js-builds-dropdown-container').is('visible')).toEqual(false); + done(); + }, 0); + }); +}); -- GitLab From c74cdd46235b659b60901c6b8846f4ca2374012d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 24 Apr 2017 16:43:24 +0100 Subject: [PATCH 2/6] Close dropwdown for vue dropdown --- .../javascripts/pipelines/components/stage.js | 41 ++++++++++++------- spec/javascripts/pipelines/stage_spec.js | 15 +++++++ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/app/assets/javascripts/pipelines/components/stage.js b/app/assets/javascripts/pipelines/components/stage.js index b8cc363061151c..21f68fc6f89e6c 100644 --- a/app/assets/javascripts/pipelines/components/stage.js +++ b/app/assets/javascripts/pipelines/components/stage.js @@ -2,13 +2,6 @@ import StatusIconEntityMap from '../../ci_status_icons'; export default { - data() { - return { - builds: '', - spinner: '', - }; - }, - props: { stage: { type: Object, @@ -16,6 +9,13 @@ export default { }, }, + data() { + return { + builds: '', + spinner: '', + }; + }, + updated() { if (this.builds) { this.stopDropdownClickPropagation(); @@ -31,7 +31,9 @@ export default { return this.$http.get(this.stage.dropdown_path) .then((response) => { this.builds = JSON.parse(response.body).html; - }, () => { + }) + .catch(() => { + $(this.$refs.dropdown).dropdown('toggle'); const flash = new Flash('Something went wrong on our end.'); return flash; }); @@ -46,9 +48,10 @@ export default { * target the click event of this component. */ stopDropdownClickPropagation() { - $(this.$el.querySelectorAll('.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item')).on('click', (e) => { - e.stopPropagation(); - }); + $(this.$el.querySelectorAll('.js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item')) + .on('click', (e) => { + e.stopPropagation(); + }); }, }, computed: { @@ -81,12 +84,20 @@ export default { data-placement="top" data-toggle="dropdown" type="button" - :aria-label="stage.title"> - - + :aria-label="stage.title" + ref="dropdown"> + +