diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/groups/milestones_controller_spec.rb | 12 | ||||
-rw-r--r-- | spec/controllers/projects/milestones_controller_spec.rb | 3 | ||||
-rw-r--r-- | spec/features/issues/issue_sidebar_spec.rb | 9 | ||||
-rw-r--r-- | spec/features/merge_requests/create_new_mr_spec.rb | 4 | ||||
-rw-r--r-- | spec/features/milestones/milestones_spec.rb | 3 | ||||
-rw-r--r-- | spec/features/triggers_spec.rb | 18 | ||||
-rw-r--r-- | spec/finders/pipelines_finder_spec.rb | 205 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/cron_parser_spec.rb | 88 | ||||
-rw-r--r-- | spec/lib/gitlab/import_export/project_tree_saver_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/ci/trigger_schedule_spec.rb | 32 | ||||
-rw-r--r-- | spec/requests/api/pipelines_spec.rb | 239 | ||||
-rw-r--r-- | spec/services/projects/enable_deploy_key_service_spec.rb | 10 | ||||
-rw-r--r-- | spec/support/milestone_tabs_examples.rb | 68 | ||||
-rw-r--r-- | spec/views/projects/commit/show.html.haml_spec.rb | 44 |
14 files changed, 695 insertions, 44 deletions
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb index 6e4b5f78e33..7cf2996ffd0 100644 --- a/spec/controllers/groups/milestones_controller_spec.rb +++ b/spec/controllers/groups/milestones_controller_spec.rb @@ -6,6 +6,16 @@ describe Groups::MilestonesController do let(:project2) { create(:empty_project, group: group) } let(:user) { create(:user) } let(:title) { '肯定不是中文的问题' } + let(:milestone) do + project_milestone = create(:milestone, project: project) + + GroupMilestone.build( + group, + [project], + project_milestone.title + ) + end + let(:milestone_path) { group_milestone_path(group, milestone.safe_title, title: milestone.title) } before do sign_in(user) @@ -14,6 +24,8 @@ describe Groups::MilestonesController do controller.instance_variable_set(:@group, group) end + it_behaves_like 'milestone tabs' + describe "#create" do it "creates group milestone with Chinese title" do post :create, diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb index 47e61c3cea8..84a61b2784e 100644 --- a/spec/controllers/projects/milestones_controller_spec.rb +++ b/spec/controllers/projects/milestones_controller_spec.rb @@ -7,6 +7,7 @@ describe Projects::MilestonesController do let(:issue) { create(:issue, project: project, milestone: milestone) } let!(:label) { create(:label, project: project, title: 'Issue Label', issues: [issue]) } let!(:merge_request) { create(:merge_request, source_project: project, target_project: project, milestone: milestone) } + let(:milestone_path) { namespace_project_milestone_path } before do sign_in(user) @@ -14,6 +15,8 @@ describe Projects::MilestonesController do controller.instance_variable_set(:@project, project) end + it_behaves_like 'milestone tabs' + describe "#show" do render_views diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 8589945ab74..82b80a69bed 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -3,7 +3,8 @@ require 'rails_helper' feature 'Issue Sidebar', feature: true do include MobileHelpers - let(:project) { create(:project, :public) } + let(:group) { create(:group, :nested) } + let(:project) { create(:project, :public, namespace: group) } let(:issue) { create(:issue, project: project) } let!(:user) { create(:user)} let!(:label) { create(:label, project: project, title: 'bug') } @@ -151,9 +152,7 @@ feature 'Issue Sidebar', feature: true do end def open_issue_sidebar - page.within('aside.right-sidebar.right-sidebar-collapsed') do - find('.js-sidebar-toggle').click - sleep 1 - end + find('aside.right-sidebar.right-sidebar-collapsed .js-sidebar-toggle').click + find('aside.right-sidebar.right-sidebar-expanded') end end diff --git a/spec/features/merge_requests/create_new_mr_spec.rb b/spec/features/merge_requests/create_new_mr_spec.rb index f0fec625108..f1b3e7f158c 100644 --- a/spec/features/merge_requests/create_new_mr_spec.rb +++ b/spec/features/merge_requests/create_new_mr_spec.rb @@ -20,7 +20,6 @@ feature 'Create New Merge Request', feature: true, js: true do expect(page).to have_content('Target branch') first('.js-source-branch').click - first('.dropdown-source-branch .dropdown-content') find('.dropdown-source-branch .dropdown-content a', match: :first).click expect(page).to have_content "b83d6e3" @@ -35,8 +34,7 @@ feature 'Create New Merge Request', feature: true, js: true do expect(page).to have_content('Target branch') first('.js-target-branch').click - first('.dropdown-target-branch .dropdown-content') - first('.dropdown-target-branch .dropdown-content a', text: 'v1.1.0').click + find('.dropdown-target-branch .dropdown-content a', text: 'v1.1.0', match: :first).click expect(page).to have_content "b83d6e3" end diff --git a/spec/features/milestones/milestones_spec.rb b/spec/features/milestones/milestones_spec.rb index 50d7ca39045..9eec3d7f270 100644 --- a/spec/features/milestones/milestones_spec.rb +++ b/spec/features/milestones/milestones_spec.rb @@ -86,6 +86,9 @@ describe 'Milestone draggable', feature: true, js: true do visit namespace_project_milestone_path(project.namespace, project, milestone) page.find("a[href='#tab-merge-requests']").click + + wait_for_ajax + scroll_into_view('.milestone-content') drag_to(selector: '.merge_requests-sortable-list', list_to_index: 1) diff --git a/spec/features/triggers_spec.rb b/spec/features/triggers_spec.rb index 81fa2de1cc3..783f330221c 100644 --- a/spec/features/triggers_spec.rb +++ b/spec/features/triggers_spec.rb @@ -104,6 +104,24 @@ feature 'Triggers', feature: true, js: true do expect(page).to have_content 'The form contains the following errors' end + + context 'when GitLab time_zone is ActiveSupport::TimeZone format' do + before do + allow(Time).to receive(:zone) + .and_return(ActiveSupport::TimeZone['Eastern Time (US & Canada)']) + end + + scenario 'do fill form with valid data and save' do + find('#trigger_trigger_schedule_attributes_active').click + fill_in 'trigger_trigger_schedule_attributes_cron', with: '1 * * * *' + fill_in 'trigger_trigger_schedule_attributes_cron_timezone', with: 'UTC' + fill_in 'trigger_trigger_schedule_attributes_ref', with: 'master' + click_button 'Save trigger' + + expect(page.find('.flash-notice')) + .to have_content 'Trigger was successfully updated.' + end + end end context 'disabling schedule' do diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb index 6bada7b3eb9..f2aeda241c1 100644 --- a/spec/finders/pipelines_finder_spec.rb +++ b/spec/finders/pipelines_finder_spec.rb @@ -3,50 +3,205 @@ require 'spec_helper' describe PipelinesFinder do let(:project) { create(:project, :repository) } - let!(:tag_pipeline) { create(:ci_pipeline, project: project, ref: 'v1.0.0') } - let!(:branch_pipeline) { create(:ci_pipeline, project: project) } - - subject { described_class.new(project).execute(params) } + subject { described_class.new(project, params).execute } describe "#execute" do - context 'when a scope is passed' do - context 'when scope is nil' do - let(:params) { { scope: nil } } + context 'when params is empty' do + let(:params) { {} } + let!(:pipelines) { create_list(:ci_pipeline, 2, project: project) } + + it 'returns all pipelines' do + is_expected.to match_array(pipelines) + end + end + + %w[running pending].each do |target| + context "when scope is #{target}" do + let(:params) { { scope: target } } + let!(:pipeline) { create(:ci_pipeline, project: project, status: target) } - it 'selects all pipelines' do - expect(subject.count).to be 2 - expect(subject).to include tag_pipeline - expect(subject).to include branch_pipeline + it 'returns matched pipelines' do + is_expected.to eq([pipeline]) end end + end + + context 'when scope is finished' do + let(:params) { { scope: 'finished' } } + let!(:pipelines) do + [create(:ci_pipeline, project: project, status: 'success'), + create(:ci_pipeline, project: project, status: 'failed'), + create(:ci_pipeline, project: project, status: 'canceled')] + end - context 'when selecting branches' do + it 'returns matched pipelines' do + is_expected.to match_array(pipelines) + end + end + + context 'when scope is branches or tags' do + let!(:pipeline_branch) { create(:ci_pipeline, project: project) } + let!(:pipeline_tag) { create(:ci_pipeline, project: project, ref: 'v1.0.0', tag: true) } + + context 'when scope is branches' do let(:params) { { scope: 'branches' } } - it 'excludes tags' do - expect(subject).not_to include tag_pipeline - expect(subject).to include branch_pipeline + it 'returns matched pipelines' do + is_expected.to eq([pipeline_branch]) end end - context 'when selecting tags' do + context 'when scope is tags' do let(:params) { { scope: 'tags' } } - it 'excludes branches' do - expect(subject).to include tag_pipeline - expect(subject).not_to include branch_pipeline + it 'returns matched pipelines' do + is_expected.to eq([pipeline_tag]) + end + end + end + + HasStatus::AVAILABLE_STATUSES.each do |target| + context "when status is #{target}" do + let(:params) { { status: target } } + let!(:pipeline) { create(:ci_pipeline, project: project, status: target) } + + before do + exception_status = HasStatus::AVAILABLE_STATUSES - [target] + create(:ci_pipeline, project: project, status: exception_status.first) + end + + it 'returns matched pipelines' do + is_expected.to eq([pipeline]) end end end - # Scoping to pending will speed up the test as it doesn't hit the FS - let(:params) { { scope: 'pending' } } + context 'when ref is specified' do + let!(:pipeline) { create(:ci_pipeline, project: project) } + + context 'when ref exists' do + let(:params) { { ref: 'master' } } + + it 'returns matched pipelines' do + is_expected.to eq([pipeline]) + end + end + + context 'when ref does not exist' do + let(:params) { { ref: 'invalid-ref' } } + + it 'returns empty' do + is_expected.to be_empty + end + end + end + + context 'when name is specified' do + let(:user) { create(:user) } + let!(:pipeline) { create(:ci_pipeline, project: project, user: user) } + + context 'when name exists' do + let(:params) { { name: user.name } } + + it 'returns matched pipelines' do + is_expected.to eq([pipeline]) + end + end + + context 'when name does not exist' do + let(:params) { { name: 'invalid-name' } } + + it 'returns empty' do + is_expected.to be_empty + end + end + end - it 'orders in descending order on ID' do - feature_pipeline = create(:ci_pipeline, project: project, ref: 'feature') + context 'when username is specified' do + let(:user) { create(:user) } + let!(:pipeline) { create(:ci_pipeline, project: project, user: user) } - expected_ids = [feature_pipeline.id, branch_pipeline.id, tag_pipeline.id].sort.reverse - expect(subject.map(&:id)).to eq expected_ids + context 'when username exists' do + let(:params) { { username: user.username } } + + it 'returns matched pipelines' do + is_expected.to eq([pipeline]) + end + end + + context 'when username does not exist' do + let(:params) { { username: 'invalid-username' } } + + it 'returns empty' do + is_expected.to be_empty + end + end + end + + context 'when yaml_errors is specified' do + let!(:pipeline1) { create(:ci_pipeline, project: project, yaml_errors: 'Syntax error') } + let!(:pipeline2) { create(:ci_pipeline, project: project) } + + context 'when yaml_errors is true' do + let(:params) { { yaml_errors: true } } + + it 'returns matched pipelines' do + is_expected.to eq([pipeline1]) + end + end + + context 'when yaml_errors is false' do + let(:params) { { yaml_errors: false } } + + it 'returns matched pipelines' do + is_expected.to eq([pipeline2]) + end + end + + context 'when yaml_errors is invalid' do + let(:params) { { yaml_errors: "invalid-yaml_errors" } } + + it 'returns all pipelines' do + is_expected.to match_array([pipeline1, pipeline2]) + end + end + end + + context 'when order_by and sort are specified' do + context 'when order_by user_id' do + let(:params) { { order_by: 'user_id', sort: 'asc' } } + let!(:pipelines) { create_list(:ci_pipeline, 2, project: project, user: create(:user)) } + + it 'sorts as user_id: :asc' do + is_expected.to match_array(pipelines) + end + + context 'when sort is invalid' do + let(:params) { { order_by: 'user_id', sort: 'invalid_sort' } } + + it 'sorts as user_id: :desc' do + is_expected.to eq(pipelines.sort_by { |p| -p.user.id }) + end + end + end + + context 'when order_by is invalid' do + let(:params) { { order_by: 'invalid_column', sort: 'asc' } } + let!(:pipelines) { create_list(:ci_pipeline, 2, project: project) } + + it 'sorts as id: :asc' do + is_expected.to eq(pipelines.sort_by { |p| p.id }) + end + end + + context 'when both are nil' do + let(:params) { { order_by: nil, sort: nil } } + let!(:pipelines) { create_list(:ci_pipeline, 2, project: project) } + + it 'sorts as id: :desc' do + is_expected.to eq(pipelines.sort_by { |p| -p.id }) + end + end end end end diff --git a/spec/lib/gitlab/ci/cron_parser_spec.rb b/spec/lib/gitlab/ci/cron_parser_spec.rb index 0864bc7258d..809fda11879 100644 --- a/spec/lib/gitlab/ci/cron_parser_spec.rb +++ b/spec/lib/gitlab/ci/cron_parser_spec.rb @@ -60,14 +60,60 @@ describe Gitlab::Ci::CronParser do end end - context 'when cron_timezone is US/Pacific' do - let(:cron) { '0 0 * * *' } - let(:cron_timezone) { 'US/Pacific' } + context 'when cron_timezone is TZInfo format' do + before do + allow(Time).to receive(:zone) + .and_return(ActiveSupport::TimeZone['UTC']) + end - it_behaves_like "returns time in the future" + let(:hour_in_utc) do + ActiveSupport::TimeZone[cron_timezone] + .now.change(hour: 0).in_time_zone('UTC').hour + end + + context 'when cron_timezone is US/Pacific' do + let(:cron) { '* 0 * * *' } + let(:cron_timezone) { 'US/Pacific' } + + it_behaves_like "returns time in the future" + + it 'converts time in server time zone' do + expect(subject.hour).to eq(hour_in_utc) + end + end + end + + context 'when cron_timezone is ActiveSupport::TimeZone format' do + before do + allow(Time).to receive(:zone) + .and_return(ActiveSupport::TimeZone['UTC']) + end + + let(:hour_in_utc) do + ActiveSupport::TimeZone[cron_timezone] + .now.change(hour: 0).in_time_zone('UTC').hour + end + + context 'when cron_timezone is Berlin' do + let(:cron) { '* 0 * * *' } + let(:cron_timezone) { 'Berlin' } + + it_behaves_like "returns time in the future" + + it 'converts time in server time zone' do + expect(subject.hour).to eq(hour_in_utc) + end + end - it 'converts time in server time zone' do - expect(subject.hour).to eq((Time.zone.now.in_time_zone(cron_timezone).utc_offset / 60 / 60).abs) + context 'when cron_timezone is Eastern Time (US & Canada)' do + let(:cron) { '* 0 * * *' } + let(:cron_timezone) { 'Eastern Time (US & Canada)' } + + it_behaves_like "returns time in the future" + + it 'converts time in server time zone' do + expect(subject.hour).to eq(hour_in_utc) + end end end end @@ -76,9 +122,21 @@ describe Gitlab::Ci::CronParser do let(:cron) { 'invalid_cron' } let(:cron_timezone) { 'invalid_cron_timezone' } - it 'returns nil' do - is_expected.to be_nil - end + it { is_expected.to be_nil } + end + + context 'when cron syntax is quoted' do + let(:cron) { "'0 * * * *'" } + let(:cron_timezone) { 'UTC' } + + it { expect(subject).to be_nil } + end + + context 'when cron syntax is rufus-scheduler syntax' do + let(:cron) { 'every 3h' } + let(:cron_timezone) { 'UTC' } + + it { expect(subject).to be_nil } end end @@ -96,6 +154,12 @@ describe Gitlab::Ci::CronParser do it { is_expected.to eq(false) } end + + context 'when cron syntax is quoted' do + let(:cron) { "'0 * * * *'" } + + it { is_expected.to eq(false) } + end end describe '#cron_timezone_valid?' do @@ -112,5 +176,11 @@ describe Gitlab::Ci::CronParser do it { is_expected.to eq(false) } end + + context 'when cron_timezone is ActiveSupport::TimeZone format' do + let(:cron_timezone) { 'Eastern Time (US & Canada)' } + + it { is_expected.to eq(true) } + end end end diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb index 6e145947104..1035428b2e7 100644 --- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do let(:project_tree_saver) { described_class.new(project: project, current_user: user, shared: shared) } let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" } let(:user) { create(:user) } - let(:project) { setup_project } + let!(:project) { setup_project } before do project.team << [user, :master] @@ -219,7 +219,7 @@ describe Gitlab::ImportExport::ProjectTreeSaver, services: true do releases: [release], group: group ) - project.update(description_html: 'description') + project.update_column(:description_html, 'description') project_label = create(:label, project: project) group_label = create(:group_label, group: group) create(:label_link, label: project_label, target: issue) diff --git a/spec/models/ci/trigger_schedule_spec.rb b/spec/models/ci/trigger_schedule_spec.rb index 75d21541cee..92447564d7c 100644 --- a/spec/models/ci/trigger_schedule_spec.rb +++ b/spec/models/ci/trigger_schedule_spec.rb @@ -73,4 +73,36 @@ describe Ci::TriggerSchedule, models: true do end end end + + describe '#real_next_run' do + subject do + Ci::TriggerSchedule.last.real_next_run(worker_cron: worker_cron, + worker_time_zone: worker_time_zone) + end + + context 'when GitLab time_zone is UTC' do + before do + allow(Time).to receive(:zone) + .and_return(ActiveSupport::TimeZone[worker_time_zone]) + end + + let(:worker_time_zone) { 'UTC' } + + context 'when cron_timezone is Eastern Time (US & Canada)' do + before do + create(:ci_trigger_schedule, :nightly, + cron_timezone: 'Eastern Time (US & Canada)') + end + + let(:worker_cron) { '0 1 2 3 *' } + + it 'returns the next time worker executes' do + expect(subject.min).to eq(0) + expect(subject.hour).to eq(1) + expect(subject.day).to eq(2) + expect(subject.month).to eq(3) + end + end + end + end end diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index 762345cd41c..f9e5316b3de 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -24,6 +24,245 @@ describe API::Pipelines do expect(json_response.first['id']).to eq pipeline.id expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status]) end + + context 'when parameter is passed' do + %w[running pending].each do |target| + context "when scope is #{target}" do + before do + create(:ci_pipeline, project: project, status: target) + end + + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), scope: target + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + json_response.each { |r| expect(r['status']).to eq(target) } + end + end + end + + context 'when scope is finished' do + before do + create(:ci_pipeline, project: project, status: 'success') + create(:ci_pipeline, project: project, status: 'failed') + create(:ci_pipeline, project: project, status: 'canceled') + end + + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), scope: 'finished' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + json_response.each { |r| expect(r['status']).to be_in(%w[success failed canceled]) } + end + end + + context 'when scope is branches or tags' do + let!(:pipeline_branch) { create(:ci_pipeline, project: project) } + let!(:pipeline_tag) { create(:ci_pipeline, project: project, ref: 'v1.0.0', tag: true) } + + context 'when scope is branches' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), scope: 'branches' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + expect(json_response.last['id']).to eq(pipeline_branch.id) + end + end + + context 'when scope is tags' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), scope: 'tags' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + expect(json_response.last['id']).to eq(pipeline_tag.id) + end + end + end + + context 'when scope is invalid' do + it 'returns bad_request' do + get api("/projects/#{project.id}/pipelines", user), scope: 'invalid-scope' + + expect(response).to have_http_status(:bad_request) + end + end + + HasStatus::AVAILABLE_STATUSES.each do |target| + context "when status is #{target}" do + before do + create(:ci_pipeline, project: project, status: target) + exception_status = HasStatus::AVAILABLE_STATUSES - [target] + create(:ci_pipeline, project: project, status: exception_status.sample) + end + + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), status: target + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + json_response.each { |r| expect(r['status']).to eq(target) } + end + end + end + + context 'when status is invalid' do + it 'returns bad_request' do + get api("/projects/#{project.id}/pipelines", user), status: 'invalid-status' + + expect(response).to have_http_status(:bad_request) + end + end + + context 'when ref is specified' do + before do + create(:ci_pipeline, project: project) + end + + context 'when ref exists' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), ref: 'master' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + json_response.each { |r| expect(r['ref']).to eq('master') } + end + end + + context 'when ref does not exist' do + it 'returns empty' do + get api("/projects/#{project.id}/pipelines", user), ref: 'invalid-ref' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).to be_empty + end + end + end + + context 'when name is specified' do + let!(:pipeline) { create(:ci_pipeline, project: project, user: user) } + + context 'when name exists' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), name: user.name + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response.first['id']).to eq(pipeline.id) + end + end + + context 'when name does not exist' do + it 'returns empty' do + get api("/projects/#{project.id}/pipelines", user), name: 'invalid-name' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).to be_empty + end + end + end + + context 'when username is specified' do + let!(:pipeline) { create(:ci_pipeline, project: project, user: user) } + + context 'when username exists' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), username: user.username + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response.first['id']).to eq(pipeline.id) + end + end + + context 'when username does not exist' do + it 'returns empty' do + get api("/projects/#{project.id}/pipelines", user), username: 'invalid-username' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).to be_empty + end + end + end + + context 'when yaml_errors is specified' do + let!(:pipeline1) { create(:ci_pipeline, project: project, yaml_errors: 'Syntax error') } + let!(:pipeline2) { create(:ci_pipeline, project: project) } + + context 'when yaml_errors is true' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), yaml_errors: true + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response.first['id']).to eq(pipeline1.id) + end + end + + context 'when yaml_errors is false' do + it 'returns matched pipelines' do + get api("/projects/#{project.id}/pipelines", user), yaml_errors: false + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response.first['id']).to eq(pipeline2.id) + end + end + + context 'when yaml_errors is invalid' do + it 'returns bad_request' do + get api("/projects/#{project.id}/pipelines", user), yaml_errors: 'invalid-yaml_errors' + + expect(response).to have_http_status(:bad_request) + end + end + end + + context 'when order_by and sort are specified' do + context 'when order_by user_id' do + let!(:pipeline) { create_list(:ci_pipeline, 2, project: project, user: create(:user)) } + + it 'sorts as user_id: :asc' do + get api("/projects/#{project.id}/pipelines", user), order_by: 'user_id', sort: 'asc' + + expect(response).to have_http_status(:ok) + expect(response).to include_pagination_headers + expect(json_response).not_to be_empty + pipeline.sort_by { |p| p.user.id }.tap do |sorted_pipeline| + json_response.each_with_index { |r, i| expect(r['id']).to eq(sorted_pipeline[i].id) } + end + end + + context 'when sort is invalid' do + it 'returns bad_request' do + get api("/projects/#{project.id}/pipelines", user), order_by: 'user_id', sort: 'invalid_sort' + + expect(response).to have_http_status(:bad_request) + end + end + end + + context 'when order_by is invalid' do + it 'returns bad_request' do + get api("/projects/#{project.id}/pipelines", user), order_by: 'lock_version', sort: 'asc' + + expect(response).to have_http_status(:bad_request) + end + end + end + end end context 'unauthorized user' do diff --git a/spec/services/projects/enable_deploy_key_service_spec.rb b/spec/services/projects/enable_deploy_key_service_spec.rb index a37510cf159..78626fbad4b 100644 --- a/spec/services/projects/enable_deploy_key_service_spec.rb +++ b/spec/services/projects/enable_deploy_key_service_spec.rb @@ -21,6 +21,16 @@ describe Projects::EnableDeployKeyService, services: true do end end + context 'add the same key twice' do + before do + project.deploy_keys << deploy_key + end + + it 'returns existing key' do + expect(service.execute).to eq(deploy_key) + end + end + def service Projects::EnableDeployKeyService.new(project, user, params) end diff --git a/spec/support/milestone_tabs_examples.rb b/spec/support/milestone_tabs_examples.rb new file mode 100644 index 00000000000..c69f8e11008 --- /dev/null +++ b/spec/support/milestone_tabs_examples.rb @@ -0,0 +1,68 @@ +shared_examples 'milestone tabs' do + def go(path, extra_params = {}) + params = if milestone.is_a?(GlobalMilestone) + { group_id: group.id, id: milestone.safe_title, title: milestone.title } + else + { namespace_id: project.namespace.to_param, project_id: project, id: milestone.iid } + end + + get path, params.merge(extra_params) + end + + describe '#merge_requests' do + context 'as html' do + before { go(:merge_requests, format: 'html') } + + it 'redirects to milestone#show' do + expect(response).to redirect_to(milestone_path) + end + end + + context 'as json' do + before { go(:merge_requests, format: 'json') } + + it 'renders the merge requests tab template to a string' do + expect(response).to render_template('shared/milestones/_merge_requests_tab') + expect(json_response).to have_key('html') + end + end + end + + describe '#participants' do + context 'as html' do + before { go(:participants, format: 'html') } + + it 'redirects to milestone#show' do + expect(response).to redirect_to(milestone_path) + end + end + + context 'as json' do + before { go(:participants, format: 'json') } + + it 'renders the participants tab template to a string' do + expect(response).to render_template('shared/milestones/_participants_tab') + expect(json_response).to have_key('html') + end + end + end + + describe '#labels' do + context 'as html' do + before { go(:labels, format: 'html') } + + it 'redirects to milestone#show' do + expect(response).to redirect_to(milestone_path) + end + end + + context 'as json' do + before { go(:labels, format: 'json') } + + it 'renders the labels tab template to a string' do + expect(response).to render_template('shared/milestones/_labels_tab') + expect(json_response).to have_key('html') + end + end + end +end diff --git a/spec/views/projects/commit/show.html.haml_spec.rb b/spec/views/projects/commit/show.html.haml_spec.rb new file mode 100644 index 00000000000..122075cc10e --- /dev/null +++ b/spec/views/projects/commit/show.html.haml_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe 'projects/commit/show.html.haml', :view do + let(:project) { create(:project, :repository) } + + before do + assign(:project, project) + assign(:repository, project.repository) + assign(:commit, project.commit) + assign(:noteable, project.commit) + assign(:notes, []) + assign(:diffs, project.commit.diffs) + + allow(view).to receive(:current_user).and_return(nil) + allow(view).to receive(:can?).and_return(false) + allow(view).to receive(:can_collaborate_with_project?).and_return(false) + allow(view).to receive(:current_ref).and_return(project.repository.root_ref) + allow(view).to receive(:diff_btn).and_return('') + end + + context 'inline diff view' do + before do + allow(view).to receive(:diff_view).and_return(:inline) + + render + end + + it 'keeps container-limited' do + expect(rendered).not_to have_selector('.limit-container-width') + end + end + + context 'parallel diff view' do + before do + allow(view).to receive(:diff_view).and_return(:parallel) + + render + end + + it 'spans full width' do + expect(rendered).to have_selector('.limit-container-width') + end + end +end |