diff options
author | Grzegorz Bizon <grzegorz@gitlab.com> | 2016-12-20 21:21:52 +0000 |
---|---|---|
committer | Grzegorz Bizon <grzegorz@gitlab.com> | 2016-12-20 21:21:52 +0000 |
commit | 92a91a880327877fe3ac1825a4c5b638333cf586 (patch) | |
tree | 5d892cda3cd9c43af94d9109345cddbf3ee27c9d /spec | |
parent | d814533f690b4dba7d32006a97f2f696161fa564 (diff) | |
parent | 2b486c2bb27087e4eb306821b9fca95ff8ac74d3 (diff) | |
download | gitlab-ce-92a91a880327877fe3ac1825a4c5b638333cf586.tar.gz |
Merge branch '19703-direct-link-pipelines' into 'master'
Resolve "Direct link from pipeline list to builds"
## What does this MR do?
- Adds a dropdown with builds in the mini pipeline graph in the pipelines table
- Unnest a lot of CSS related with pipelines in order to make it reusable
## Screenshots
![Screen_Shot_2016-12-15_at_14.45.41](/uploads/ca1c61842a422a34383e029d668034b7/Screen_Shot_2016-12-15_at_14.45.41.png)
![Screen_Shot_2016-12-15_at_14.45.49](/uploads/952e3277143639ce4ad111103034faeb/Screen_Shot_2016-12-15_at_14.45.49.png)
![Screen_Shot_2016-12-15_at_14.46.02](/uploads/f7369a124b1c3c0db4194de2cb637ef0/Screen_Shot_2016-12-15_at_14.46.02.png)
![graph_animation](/uploads/9bae036cb5acff499f992a4722943d72/graph_animation.gif)
## Does this MR meet the acceptance criteria?
- [x] [Changelog entry](https://docs.gitlab.com/ce/development/changelog.html) added
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- Tests
- [x] Added for this feature/bug
- [ ] All builds are passing
- [x] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html)
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if it does - rebase it please)
- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
## What are the relevant issue numbers?
Closes #25071
Closes #19703
See merge request !8097
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/projects/pipelines_controller_spec.rb | 47 | ||||
-rw-r--r-- | spec/features/projects/pipelines/pipeline_spec.rb | 2 | ||||
-rw-r--r-- | spec/features/projects/pipelines/pipelines_spec.rb | 72 | ||||
-rw-r--r-- | spec/javascripts/fixtures/mini_dropdown_graph.html.haml | 8 | ||||
-rw-r--r-- | spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 | 51 | ||||
-rw-r--r-- | spec/models/ci/pipeline_spec.rb | 24 | ||||
-rw-r--r-- | spec/models/ci/stage_spec.rb | 13 | ||||
-rw-r--r-- | spec/views/projects/pipelines/_stage.html.haml_spec.rb | 21 |
8 files changed, 229 insertions, 9 deletions
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb new file mode 100644 index 00000000000..5fe7e6407cc --- /dev/null +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -0,0 +1,47 @@ +require 'spec_helper' + +describe Projects::PipelinesController do + include ApiHelpers + + let(:user) { create(:user) } + let(:project) { create(:empty_project, :public) } + let(:pipeline) { create(:ci_pipeline, project: project) } + + before do + sign_in(user) + end + + describe 'GET stages.json' do + context 'when accessing existing stage' do + before do + create(:ci_build, pipeline: pipeline, stage: 'build') + + get_stage('build') + end + + it 'returns html source for stage dropdown' do + expect(response).to have_http_status(:ok) + expect(response).to render_template('projects/pipelines/_stage') + expect(json_response).to include('html') + end + end + + context 'when accessing unknown stage' do + before do + get_stage('test') + end + + it 'responds with not found' do + expect(response).to have_http_status(:not_found) + end + end + + def get_stage(name) + get :stage, namespace_id: project.namespace.path, + project_id: project.path, + id: pipeline.id, + stage: name, + format: :json + end + end +end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 1210e2745db..14e009daba8 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe "Pipelines", feature: true, js: true do +describe 'Pipeline', :feature, :js do include GitlabRoutingHelper let(:project) { create(:empty_project) } diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index f3731698a18..1ff57f92c4c 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -1,7 +1,8 @@ require 'spec_helper' -describe "Pipelines" do +describe 'Pipelines', :feature, :js do include GitlabRoutingHelper + include WaitForAjax let(:project) { create(:empty_project) } let(:user) { create(:user) } @@ -69,16 +70,32 @@ describe "Pipelines" do end context 'with manual actions' do - let!(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'manual build', stage: 'test', commands: 'test') } + let!(:manual) do + create(:ci_build, :manual, pipeline: pipeline, + name: 'manual build', + stage: 'test', + commands: 'test') + end - before { visit namespace_project_pipelines_path(project.namespace, project) } + before do + visit namespace_project_pipelines_path(project.namespace, project) + end - it { expect(page).to have_link('Manual build') } + it 'has link to the manual action' do + find('.js-pipeline-dropdown-manual-actions').click - context 'when playing' do - before { click_link('Manual build') } + expect(page).to have_link('Manual build') + end - it { expect(manual.reload).to be_pending } + context 'when manual action was played' do + before do + find('.js-pipeline-dropdown-manual-actions').click + click_link('Manual build') + end + + it 'enqueues manual action job' do + expect(manual.reload).to be_pending + end end end @@ -131,7 +148,10 @@ describe "Pipelines" do before { visit namespace_project_pipelines_path(project.namespace, project) } it { expect(page).to have_selector('.build-artifacts') } - it { expect(page).to have_link(with_artifacts.name) } + it do + find('.js-pipeline-dropdown-download').click + expect(page).to have_link(with_artifacts.name) + end end context 'with artifacts expired' do @@ -150,6 +170,42 @@ describe "Pipelines" do it { expect(page).not_to have_selector('.build-artifacts') } end end + + context 'mini pipleine graph' do + let!(:build) do + create(:ci_build, pipeline: pipeline, stage: 'build', name: 'build') + end + + before do + visit namespace_project_pipelines_path(project.namespace, project) + end + + it 'should render a mini pipeline graph' do + endpoint = stage_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline, stage: build.name) + + expect(page).to have_selector('.mini-pipeline-graph') + expect(page).to have_selector(".js-builds-dropdown-button[data-stage-endpoint='#{endpoint}']") + end + + context 'when clicking a graph stage' do + it 'should open a dropdown' do + find('.js-builds-dropdown-button').trigger('click') + + wait_for_ajax + + expect(page).to have_link build.name + end + + it 'should be possible to retry the failed build' do + find('.js-builds-dropdown-button').trigger('click') + + wait_for_ajax + + find('a.ci-action-icon-container').trigger('click') + expect(page).not_to have_content('Cancel running') + end + end + end end describe 'POST /:project/pipelines' do diff --git a/spec/javascripts/fixtures/mini_dropdown_graph.html.haml b/spec/javascripts/fixtures/mini_dropdown_graph.html.haml new file mode 100644 index 00000000000..e9bf7568e95 --- /dev/null +++ b/spec/javascripts/fixtures/mini_dropdown_graph.html.haml @@ -0,0 +1,8 @@ +%div.js-builds-dropdown-tests + %button.dropdown.js-builds-dropdown-button{'data-stage-endpoint' => 'foobar'} + Dropdown + %div.js-builds-dropdown-container + %div.js-builds-dropdown-list + + %div.js-builds-dropdown-loading.builds-dropdown-loading.hidden + %span.fa.fa-spinner.fa-spin diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 new file mode 100644 index 00000000000..d1793e9308e --- /dev/null +++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js.es6 @@ -0,0 +1,51 @@ +/* eslint-disable no-new */ + +//= require flash +//= require mini_pipeline_graph_dropdown + +(() => { + describe('Mini Pipeline Graph Dropdown', () => { + fixture.preload('mini_dropdown_graph'); + + beforeEach(() => { + fixture.load('mini_dropdown_graph'); + }); + + describe('When is initialized', () => { + it('should initialize without errors when no options are given', () => { + const miniPipelineGraph = new window.gl.MiniPipelineGraph(); + + expect(miniPipelineGraph.dropdownListSelector).toEqual('.js-builds-dropdown-container'); + }); + + it('should set the container as the given prop', () => { + const container = '.foo'; + + const miniPipelineGraph = new window.gl.MiniPipelineGraph({ container }); + + expect(miniPipelineGraph.container).toEqual(container); + }); + }); + + describe('When dropdown is clicked', () => { + it('should call getBuildsList', () => { + const getBuildsListSpy = spyOn(gl.MiniPipelineGraph.prototype, 'getBuildsList').and.callFake(function () {}); + + new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }); + + document.querySelector('.js-builds-dropdown-button').click(); + + expect(getBuildsListSpy).toHaveBeenCalled(); + }); + + it('should make a request to the endpoint provided in the html', () => { + const ajaxSpy = spyOn($, 'ajax').and.callFake(function () {}); + + new gl.MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }); + + document.querySelector('.js-builds-dropdown-button').click(); + expect(ajaxSpy.calls.allArgs()[0][0].url).toEqual('foobar'); + }); + }); + }); +})(); diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 52dd41065e9..dc377d15f15 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -175,6 +175,30 @@ describe Ci::Pipeline, models: true do end end + describe '#stage' do + subject { pipeline.stage('test') } + + context 'with status in stage' do + before do + create(:commit_status, pipeline: pipeline, stage: 'test') + end + + it { expect(subject).to be_a Ci::Stage } + it { expect(subject.name).to eq 'test' } + it { expect(subject.statuses).not_to be_empty } + end + + context 'without status in stage' do + before do + create(:commit_status, pipeline: pipeline, stage: 'build') + end + + it 'return stage object' do + is_expected.to be_nil + end + end + end + describe 'state machine' do let(:current) { Time.now.change(usec: 0) } let(:build) { create_build('build1', 0) } diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb index 8fff38f7cda..742bedb37e4 100644 --- a/spec/models/ci/stage_spec.rb +++ b/spec/models/ci/stage_spec.rb @@ -28,6 +28,19 @@ describe Ci::Stage, models: true do end end + describe '#statuses_count' do + before do + create_job(:ci_build) + create_job(:ci_build, stage: 'other stage') + end + + subject { stage.statuses_count } + + it "counts statuses only from current stage" do + is_expected.to eq(1) + end + end + describe '#builds' do let!(:stage_build) { create_job(:ci_build) } let!(:commit_status) { create_job(:commit_status) } diff --git a/spec/views/projects/pipelines/_stage.html.haml_spec.rb b/spec/views/projects/pipelines/_stage.html.haml_spec.rb new file mode 100644 index 00000000000..eb7f7ca4a1a --- /dev/null +++ b/spec/views/projects/pipelines/_stage.html.haml_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe 'projects/pipelines/_stage', :view do + let(:project) { create(:project) } + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:stage) { build(:ci_stage, pipeline: pipeline) } + + before do + assign :stage, stage + + create(:ci_build, name: 'test:build', + stage: stage.name, + pipeline: pipeline) + end + + it 'shows the builds in the stage' do + render + + expect(rendered).to have_text 'test:build' + end +end |