From 8e7f19c60bea4eec86844be1e0db12ebf30f105e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 2 Dec 2017 22:55:49 -0800 Subject: Add button to run scheduled pipeline immediately Closes #38741 --- .../projects/pipeline_schedules_controller_spec.rb | 26 +++++++++++++++- spec/workers/run_pipeline_schedule_worker_spec.rb | 36 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 spec/workers/run_pipeline_schedule_worker_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 4e52e261920..384a407a100 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -96,7 +96,7 @@ describe Projects::PipelineSchedulesController do end end - context 'when variables_attributes has two variables and duplicted' do + context 'when variables_attributes has two variables and duplicated' do let(:schedule) do basic_param.merge({ variables_attributes: [{ key: 'AAA', value: 'AAA123' }, { key: 'AAA', value: 'BBB123' }] @@ -364,6 +364,30 @@ describe Projects::PipelineSchedulesController do end end + describe 'POST #run' do + set(:user) { create(:user) } + + context 'when a developer makes the request' do + before do + project.add_developer(user) + sign_in(user) + end + + it 'executes a new pipeline' do + expect(RunPipelineScheduleWorker).to receive(:perform_async).with(pipeline_schedule.id, user.id).and_return('job-123') + + go + + expect(flash[:notice]).to eq 'Successfully scheduled pipeline to run immediately' + expect(response).to have_gitlab_http_status(302) + end + end + + def go + post :run, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id + end + end + describe 'DELETE #destroy' do set(:user) { create(:user) } diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb new file mode 100644 index 00000000000..4a88ac51f62 --- /dev/null +++ b/spec/workers/run_pipeline_schedule_worker_spec.rb @@ -0,0 +1,36 @@ +require 'spec_helper' + +describe RunPipelineScheduleWorker do + describe '#perform' do + let(:project) { create(:project) } + let(:worker) { described_class.new } + let(:user) { create(:user) } + let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) } + + context 'when a project not found' do + it 'does not call the Service' do + expect(Ci::CreatePipelineService).not_to receive(:new) + expect { worker.perform(100000, user.id) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'when a user not found' do + it 'does not call the Service' do + expect(Ci::CreatePipelineService).not_to receive(:new) + expect { worker.perform(pipeline_schedule.id, 10000) }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context 'when everything is ok' do + let(:project) { create(:project) } + let(:create_pipeline_service) { instance_double(Ci::CreatePipelineService) } + + it 'calls the Service' do + expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service) + expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule) + + worker.perform(pipeline_schedule.id, user.id) + end + end + end +end -- cgit v1.2.1 From f6966cfa63fab7e3c8847d69101c6c6a444fb85f Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 5 Dec 2017 22:24:20 -0800 Subject: Address some comments with running a pipeline schedule --- .../projects/pipeline_schedules_controller_spec.rb | 4 ++-- spec/workers/run_pipeline_schedule_worker_spec.rb | 15 +++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 384a407a100..e875f5bce08 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -364,7 +364,7 @@ describe Projects::PipelineSchedulesController do end end - describe 'POST #run' do + describe 'POST #play' do set(:user) { create(:user) } context 'when a developer makes the request' do @@ -384,7 +384,7 @@ describe Projects::PipelineSchedulesController do end def go - post :run, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id + post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id end end diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb index 4a88ac51f62..481a84837f9 100644 --- a/spec/workers/run_pipeline_schedule_worker_spec.rb +++ b/spec/workers/run_pipeline_schedule_worker_spec.rb @@ -2,27 +2,30 @@ require 'spec_helper' describe RunPipelineScheduleWorker do describe '#perform' do - let(:project) { create(:project) } + set(:project) { create(:project) } + set(:user) { create(:user) } + set(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) } let(:worker) { described_class.new } - let(:user) { create(:user) } - let(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project ) } context 'when a project not found' do it 'does not call the Service' do expect(Ci::CreatePipelineService).not_to receive(:new) - expect { worker.perform(100000, user.id) }.to raise_error(ActiveRecord::RecordNotFound) + expect(worker).not_to receive(:run_pipeline_schedule) + + worker.perform(100000, user.id) end end context 'when a user not found' do it 'does not call the Service' do expect(Ci::CreatePipelineService).not_to receive(:new) - expect { worker.perform(pipeline_schedule.id, 10000) }.to raise_error(ActiveRecord::RecordNotFound) + expect(worker).not_to receive(:run_pipeline_schedule) + + worker.perform(pipeline_schedule.id, 10000) end end context 'when everything is ok' do - let(:project) { create(:project) } let(:create_pipeline_service) { instance_double(Ci::CreatePipelineService) } it 'calls the Service' do -- cgit v1.2.1 From bc2d32aca0be46250bd02c9312d1064df024b621 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 5 Dec 2017 23:23:59 -0800 Subject: Create a play_pipeline_schedule policy and use it --- .../projects/pipeline_schedules_controller_spec.rb | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index e875f5bce08..3878b0a5e4f 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -3,8 +3,8 @@ require 'spec_helper' describe Projects::PipelineSchedulesController do include AccessMatchersForController - set(:project) { create(:project, :public) } - let!(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) } + set(:project) { create(:project, :public, :repository) } + set(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) } describe 'GET #index' do let(:scope) { nil } @@ -366,25 +366,36 @@ describe Projects::PipelineSchedulesController do describe 'POST #play' do set(:user) { create(:user) } + let(:ref) { 'master' } context 'when a developer makes the request' do before do project.add_developer(user) + sign_in(user) end it 'executes a new pipeline' do expect(RunPipelineScheduleWorker).to receive(:perform_async).with(pipeline_schedule.id, user.id).and_return('job-123') - go + post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id expect(flash[:notice]).to eq 'Successfully scheduled pipeline to run immediately' expect(response).to have_gitlab_http_status(302) end end - def go - post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id + context 'when a developer attempts to schedule a protected ref' do + it 'does not allow pipeline to be executed' do + create(:protected_branch, project: project, name: ref) + protected_schedule = create(:ci_pipeline_schedule, project: project, ref: ref) + + expect(RunPipelineScheduleWorker).not_to receive(:perform_async) + + post :play, namespace_id: project.namespace.to_param, project_id: project, id: protected_schedule.id + + expect(response).to have_gitlab_http_status(404) + end end end -- cgit v1.2.1 From ad3732955389024b8a209455f9a889d5ebf411b9 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 7 Dec 2017 23:49:55 -0800 Subject: Refactor common protected ref check --- spec/policies/ci/pipeline_schedule_policy_spec.rb | 92 +++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 spec/policies/ci/pipeline_schedule_policy_spec.rb (limited to 'spec') diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb new file mode 100644 index 00000000000..1b0e9fac355 --- /dev/null +++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb @@ -0,0 +1,92 @@ +require 'spec_helper' + +describe Ci::PipelineSchedulePolicy, :models do + set(:user) { create(:user) } + set(:project) { create(:project, :repository) } + set(:pipeline_schedule) { create(:ci_pipeline_schedule, :nightly, project: project) } + + let(:policy) do + described_class.new(user, pipeline_schedule) + end + + describe 'rules' do + describe 'rules for protected ref' do + before do + project.add_developer(user) + end + + context 'when no one can push or merge to the branch' do + before do + create(:protected_branch, :no_one_can_push, + name: pipeline_schedule.ref, project: project) + end + + it 'does not include ability to play pipeline schedule' do + expect(policy).to be_disallowed :play_pipeline_schedule + end + end + + context 'when developers can push to the branch' do + before do + create(:protected_branch, :developers_can_merge, + name: pipeline_schedule.ref, project: project) + end + + it 'includes ability to update pipeline' do + expect(policy).to be_allowed :play_pipeline_schedule + end + end + + context 'when no one can create the tag' do + let(:tag) { 'v1.0.0' } + + before do + pipeline_schedule.update(ref: tag) + + create(:protected_tag, :no_one_can_create, + name: pipeline_schedule.ref, project: project) + end + + it 'does not include ability to play pipeline schedule' do + expect(policy).to be_disallowed :play_pipeline_schedule + end + end + + context 'when no one can create the tag but it is not a tag' do + before do + create(:protected_tag, :no_one_can_create, + name: pipeline_schedule.ref, project: project) + end + + it 'includes ability to play pipeline schedule' do + expect(policy).to be_allowed :play_pipeline_schedule + end + end + end + + describe 'rules for owner of schedule' do + before do + project.add_developer(user) + pipeline_schedule.update(owner: user) + end + + it 'includes abilities to do do all operations on pipeline schedule' do + expect(policy).to be_allowed :play_pipeline_schedule + expect(policy).to be_allowed :update_pipeline_schedule + expect(policy).to be_allowed :admin_pipeline_schedule + end + end + + describe 'rules for a master' do + before do + project.add_master(user) + end + + it 'includes abilities to do do all operations on pipeline schedule' do + expect(policy).to be_allowed :play_pipeline_schedule + expect(policy).to be_allowed :update_pipeline_schedule + expect(policy).to be_allowed :admin_pipeline_schedule + end + end + end +end -- cgit v1.2.1 From 0ea70802e19cbe11c6af0f6750200bb137225940 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Thu, 7 Dec 2017 23:58:05 -0800 Subject: Fix Sidekiq worker and make flash message return a link to the pipelines page --- spec/controllers/projects/pipeline_schedules_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 3878b0a5e4f..debc20ee467 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -380,7 +380,7 @@ describe Projects::PipelineSchedulesController do post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id - expect(flash[:notice]).to eq 'Successfully scheduled pipeline to run immediately' + expect(flash[:notice]).to start_with 'Successfully scheduled a pipeline to run' expect(response).to have_gitlab_http_status(302) end end -- cgit v1.2.1 From f8c3a58a54d622193a0cf15777a0d0631289278c Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 8 Dec 2017 22:20:28 -0800 Subject: Avoid Gitaly N+1 calls by caching tag_names --- spec/controllers/projects/pipeline_schedules_controller_spec.rb | 2 ++ spec/models/repository_spec.rb | 9 +++++++++ 2 files changed, 11 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index debc20ee467..8888573e882 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -7,6 +7,8 @@ describe Projects::PipelineSchedulesController do set(:pipeline_schedule) { create(:ci_pipeline_schedule, project: project) } describe 'GET #index' do + render_views + let(:scope) { nil } let!(:inactive_pipeline_schedule) do create(:ci_pipeline_schedule, :inactive, project: project) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 129fce74f45..08eb563082f 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1157,6 +1157,15 @@ describe Repository do end end + describe '#tag_exists?' do + it 'uses tag_names' do + allow(repository).to receive(:tag_names).and_return(['foobar']) + + expect(repository.tag_exists?('foobar')).to eq(true) + expect(repository.tag_exists?('master')).to eq(false) + end + end + describe '#branch_names', :use_clean_rails_memory_store_caching do let(:fake_branch_names) { ['foobar'] } -- cgit v1.2.1 From 54f13b1ec8542dc5085e0367734e8344c2c3d01e Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 9 Dec 2017 01:01:42 -0800 Subject: Add rate limiting to guard against excessive scheduling of pipelines --- spec/controllers/projects/pipeline_schedules_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 8888573e882..844c62ef005 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -366,7 +366,7 @@ describe Projects::PipelineSchedulesController do end end - describe 'POST #play' do + describe 'POST #play', :clean_gitlab_redis_cache do set(:user) { create(:user) } let(:ref) { 'master' } -- cgit v1.2.1 From ef78f67f4a2e19d204f5f4d4770649be1fe7bee9 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 9 Dec 2017 15:08:27 -0800 Subject: Add a spec for rate limiting pipeline schedules --- .../controllers/projects/pipeline_schedules_controller_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index 844c62ef005..ffc1259eb8f 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -385,6 +385,16 @@ describe Projects::PipelineSchedulesController do expect(flash[:notice]).to start_with 'Successfully scheduled a pipeline to run' expect(response).to have_gitlab_http_status(302) end + + it 'prevents users from scheduling the same pipeline repeatedly' do + 2.times do + post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id + end + + expect(flash.to_a.size).to eq(2) + expect(flash[:alert]).to eq 'You cannot play this scheduled pipeline at the moment. Please wait a minute.' + expect(response).to have_gitlab_http_status(302) + end end context 'when a developer attempts to schedule a protected ref' do -- cgit v1.2.1 From 8b939bfab769810ba56f5f4ca18632fd7ae435db Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Sat, 9 Dec 2017 15:45:01 -0800 Subject: Add spec for ActionRateLimiter --- spec/lib/gitlab/action_rate_limiter_spec.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 spec/lib/gitlab/action_rate_limiter_spec.rb (limited to 'spec') diff --git a/spec/lib/gitlab/action_rate_limiter_spec.rb b/spec/lib/gitlab/action_rate_limiter_spec.rb new file mode 100644 index 00000000000..84661605623 --- /dev/null +++ b/spec/lib/gitlab/action_rate_limiter_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe Gitlab::ActionRateLimiter do + let(:redis) { double('redis') } + let(:key) { 'user:1' } + let(:cache_key) { "action_rate_limiter:test_action:#{key}" } + + subject { described_class.new(action: :test_action, expiry_time: 100) } + + before do + allow(Gitlab::Redis::Cache).to receive(:with).and_yield(redis) + end + + it 'increases the throttle count and sets the expire time' do + expect(redis).to receive(:incr).with(cache_key).and_return(1) + expect(redis).to receive(:expire).with(cache_key, 100) + + expect(subject.throttled?(key, 1)).to be false + end + + it 'returns true if the key is throttled' do + expect(redis).to receive(:incr).with(cache_key).and_return(2) + expect(redis).not_to receive(:expire) + + expect(subject.throttled?(key, 1)).to be true + end +end -- cgit v1.2.1 From 4b0465f20de1bf58326c7daf6876b63438f00d84 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Tue, 12 Dec 2017 15:46:05 -0800 Subject: Address review comments with playing pipeline scheduler --- .../projects/pipeline_schedules_controller_spec.rb | 20 +++++++++++++++++--- spec/lib/gitlab/action_rate_limiter_spec.rb | 6 ++++-- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipeline_schedules_controller_spec.rb b/spec/controllers/projects/pipeline_schedules_controller_spec.rb index ffc1259eb8f..966ffdf6996 100644 --- a/spec/controllers/projects/pipeline_schedules_controller_spec.rb +++ b/spec/controllers/projects/pipeline_schedules_controller_spec.rb @@ -370,13 +370,27 @@ describe Projects::PipelineSchedulesController do set(:user) { create(:user) } let(:ref) { 'master' } - context 'when a developer makes the request' do + before do + project.add_developer(user) + + sign_in(user) + end + + context 'when an anonymous user makes the request' do before do - project.add_developer(user) + sign_out(user) + end - sign_in(user) + it 'does not allow pipeline to be executed' do + expect(RunPipelineScheduleWorker).not_to receive(:perform_async) + + post :play, namespace_id: project.namespace.to_param, project_id: project, id: pipeline_schedule.id + + expect(response).to have_gitlab_http_status(404) end + end + context 'when a developer makes the request' do it 'executes a new pipeline' do expect(RunPipelineScheduleWorker).to receive(:perform_async).with(pipeline_schedule.id, user.id).and_return('job-123') diff --git a/spec/lib/gitlab/action_rate_limiter_spec.rb b/spec/lib/gitlab/action_rate_limiter_spec.rb index 84661605623..542fc03e555 100644 --- a/spec/lib/gitlab/action_rate_limiter_spec.rb +++ b/spec/lib/gitlab/action_rate_limiter_spec.rb @@ -2,8 +2,10 @@ require 'spec_helper' describe Gitlab::ActionRateLimiter do let(:redis) { double('redis') } - let(:key) { 'user:1' } - let(:cache_key) { "action_rate_limiter:test_action:#{key}" } + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:key) { [user, project] } + let(:cache_key) { "action_rate_limiter:test_action:user:#{user.id}:project:#{project.id}" } subject { described_class.new(action: :test_action, expiry_time: 100) } -- cgit v1.2.1 From 558c971e3198c3127320402c8d060243c7b28daa Mon Sep 17 00:00:00 2001 From: Tiago Botelho Date: Mon, 11 Dec 2017 11:35:03 +0000 Subject: Fork and Import jobs only get marked as failed when the number of Sidekiq retries were exhausted --- .../concerns/project_import_options_spec.rb | 40 ++++++++++++++++++++++ spec/workers/repository_fork_worker_spec.rb | 29 +++++++--------- spec/workers/repository_import_worker_spec.rb | 23 +++++-------- 3 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 spec/workers/concerns/project_import_options_spec.rb (limited to 'spec') diff --git a/spec/workers/concerns/project_import_options_spec.rb b/spec/workers/concerns/project_import_options_spec.rb new file mode 100644 index 00000000000..b6c111df8b9 --- /dev/null +++ b/spec/workers/concerns/project_import_options_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe ProjectImportOptions do + let(:project) { create(:project, :import_started) } + let(:job) { { 'args' => [project.id, nil, nil], 'jid' => '123' } } + let(:worker_class) do + Class.new do + include Sidekiq::Worker + include ProjectImportOptions + end + end + + it 'sets default retry limit' do + expect(worker_class.sidekiq_options['retry']).to eq(ProjectImportOptions::IMPORT_RETRY_COUNT) + end + + it 'sets default status expiration' do + expect(worker_class.sidekiq_options['status_expiration']).to eq(StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION) + end + + describe '.sidekiq_retries_exhausted' do + it 'marks fork as failed' do + expect { worker_class.sidekiq_retries_exhausted_block.call(job) }.to change { project.reload.import_status }.from("started").to("failed") + end + + it 'logs the appropriate error message for forked projects' do + allow_any_instance_of(Project).to receive(:forked?).and_return(true) + + worker_class.sidekiq_retries_exhausted_block.call(job) + + expect(project.reload.import_error).to include("fork") + end + + it 'logs the appropriate error message for forked projects' do + worker_class.sidekiq_retries_exhausted_block.call(job) + + expect(project.reload.import_error).to include("import") + end + end +end diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index 74c85848b7e..31598586f59 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -1,17 +1,21 @@ require 'spec_helper' describe RepositoryForkWorker do - let(:project) { create(:project, :repository) } - let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) } - let(:shell) { Gitlab::Shell.new } - - subject { described_class.new } - - before do - allow(subject).to receive(:gitlab_shell).and_return(shell) + describe 'modules' do + it 'includes ProjectImportOptions' do + expect(described_class).to include_module(ProjectImportOptions) + end end describe "#perform" do + let(:project) { create(:project, :repository) } + let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) } + let(:shell) { Gitlab::Shell.new } + + before do + allow(subject).to receive(:gitlab_shell).and_return(shell) + end + def perform! subject.perform(fork_project.id, '/test/path', project.disk_path) end @@ -60,14 +64,7 @@ describe RepositoryForkWorker do expect_fork_repository.and_return(false) - expect { perform! }.to raise_error(RepositoryForkWorker::ForkError, error_message) - end - - it 'handles unexpected error' do - expect_fork_repository.and_raise(RuntimeError) - - expect { perform! }.to raise_error(RepositoryForkWorker::ForkError) - expect(fork_project.reload.import_status).to eq('failed') + expect { perform! }.to raise_error(StandardError, error_message) end end end diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index 0af537647ad..85ac14eb347 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -1,11 +1,15 @@ require 'spec_helper' describe RepositoryImportWorker do - let(:project) { create(:project, :import_scheduled) } - - subject { described_class.new } + describe 'modules' do + it 'includes ProjectImportOptions' do + expect(described_class).to include_module(ProjectImportOptions) + end + end describe '#perform' do + let(:project) { create(:project, :import_scheduled) } + context 'when worker was reset without cleanup' do let(:jid) { '12345678' } let(:started_project) { create(:project, :import_started, import_jid: jid) } @@ -44,22 +48,11 @@ describe RepositoryImportWorker do expect do subject.perform(project.id) - end.to raise_error(RepositoryImportWorker::ImportError, error) + end.to raise_error(StandardError, error) expect(project.reload.import_jid).not_to be_nil end end - context 'with unexpected error' do - it 'marks import as failed' do - allow_any_instance_of(Projects::ImportService).to receive(:execute).and_raise(RuntimeError) - - expect do - subject.perform(project.id) - end.to raise_error(RepositoryImportWorker::ImportError) - expect(project.reload.import_status).to eq('failed') - end - end - context 'when using an asynchronous importer' do it 'does not mark the import process as finished' do service = double(:service) -- cgit v1.2.1 From eaf2f48dc7db706fa1dea050543667f8cdebd4c4 Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Dec 2017 10:21:49 +0000 Subject: Export and use Notes ES module --- spec/javascripts/merge_request_notes_spec.js | 4 +--- spec/javascripts/merge_request_tabs_spec.js | 19 +++++++++---------- spec/javascripts/notes_spec.js | 4 +--- 3 files changed, 11 insertions(+), 16 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/merge_request_notes_spec.js b/spec/javascripts/merge_request_notes_spec.js index 6054b75d0b8..e983e4de3fc 100644 --- a/spec/javascripts/merge_request_notes_spec.js +++ b/spec/javascripts/merge_request_notes_spec.js @@ -1,11 +1,9 @@ -/* global Notes */ - import 'autosize'; import '~/gl_form'; import '~/lib/utils/text_utility'; import '~/render_gfm'; import '~/render_math'; -import '~/notes'; +import Notes from '~/notes'; const upArrowKeyCode = 38; diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js index 31426ceb110..050f0ea9ebd 100644 --- a/spec/javascripts/merge_request_tabs_spec.js +++ b/spec/javascripts/merge_request_tabs_spec.js @@ -1,5 +1,4 @@ /* eslint-disable no-var, comma-dangle, object-shorthand */ -/* global Notes */ import * as urlUtils from '~/lib/utils/url_utility'; import MergeRequestTabs from '~/merge_request_tabs'; @@ -7,7 +6,7 @@ import '~/commit/pipelines/pipelines_bundle'; import '~/breakpoints'; import '~/lib/utils/common_utils'; import Diff from '~/diff'; -import '~/notes'; +import Notes from '~/notes'; import 'vendor/jquery.scrollTo'; (function () { @@ -279,8 +278,8 @@ import 'vendor/jquery.scrollTo'; loadFixtures('merge_requests/diff_comment.html.raw'); $('body').attr('data-page', 'projects:merge_requests:show'); window.gl.ImageFile = () => {}; - window.notes = new Notes('', []); - spyOn(window.notes, 'toggleDiffNote').and.callThrough(); + Notes.initialize('', []); + spyOn(Notes.instance, 'toggleDiffNote').and.callThrough(); }); afterEach(() => { @@ -338,7 +337,7 @@ import 'vendor/jquery.scrollTo'; this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); expect(noteId.length).toBeGreaterThan(0); - expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({ + expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({ target: jasmine.any(Object), lineType: 'old', forceShow: true, @@ -349,7 +348,7 @@ import 'vendor/jquery.scrollTo'; spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); - expect(window.notes.toggleDiffNote).not.toHaveBeenCalled(); + expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled(); }); }); @@ -359,7 +358,7 @@ import 'vendor/jquery.scrollTo'; this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); expect(noteLineNumId.length).toBeGreaterThan(0); - expect(window.notes.toggleDiffNote).not.toHaveBeenCalled(); + expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled(); }); }); }); @@ -393,7 +392,7 @@ import 'vendor/jquery.scrollTo'; this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); expect(noteId.length).toBeGreaterThan(0); - expect(window.notes.toggleDiffNote).toHaveBeenCalledWith({ + expect(Notes.instance.toggleDiffNote).toHaveBeenCalledWith({ target: jasmine.any(Object), lineType: 'new', forceShow: true, @@ -404,7 +403,7 @@ import 'vendor/jquery.scrollTo'; spyOn(urlUtils, 'getLocationHash').and.returnValue('note_something-that-does-not-exist'); this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); - expect(window.notes.toggleDiffNote).not.toHaveBeenCalled(); + expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled(); }); }); @@ -414,7 +413,7 @@ import 'vendor/jquery.scrollTo'; this.class.loadDiff('/foo/bar/merge_requests/1/diffs'); expect(noteLineNumId.length).toBeGreaterThan(0); - expect(window.notes.toggleDiffNote).not.toHaveBeenCalled(); + expect(Notes.instance.toggleDiffNote).not.toHaveBeenCalled(); }); }); }); diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js index e09b8dc7fc5..167f074fb9b 100644 --- a/spec/javascripts/notes_spec.js +++ b/spec/javascripts/notes_spec.js @@ -1,12 +1,10 @@ /* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, max-len */ -/* global Notes */ - import * as urlUtils from '~/lib/utils/url_utility'; import 'autosize'; import '~/gl_form'; import '~/lib/utils/text_utility'; import '~/render_gfm'; -import '~/notes'; +import Notes from '~/notes'; (function() { window.gon || (window.gon = {}); -- cgit v1.2.1 From 6a33587182ef13179d2dc00a6698cb42f2e7138e Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 15 Dec 2017 12:57:08 +0000 Subject: Exported JS classes as modules --- spec/javascripts/collapsed_sidebar_todo_spec.js | 3 +-- spec/javascripts/line_highlighter_spec.js | 3 +-- spec/javascripts/merge_request_spec.js | 3 +-- spec/javascripts/right_sidebar_spec.js | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/collapsed_sidebar_todo_spec.js b/spec/javascripts/collapsed_sidebar_todo_spec.js index 974815fe939..5026eaafaca 100644 --- a/spec/javascripts/collapsed_sidebar_todo_spec.js +++ b/spec/javascripts/collapsed_sidebar_todo_spec.js @@ -1,7 +1,6 @@ -/* global Sidebar */ /* eslint-disable no-new */ import _ from 'underscore'; -import '~/right_sidebar'; +import Sidebar from '~/right_sidebar'; describe('Issuable right sidebar collapsed todo toggle', () => { const fixtureName = 'issues/open-issue.html.raw'; diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js index 645664a5219..89f4b85541d 100644 --- a/spec/javascripts/line_highlighter_spec.js +++ b/spec/javascripts/line_highlighter_spec.js @@ -1,7 +1,6 @@ /* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, jasmine/no-spec-dupes, no-underscore-dangle, max-len */ -/* global LineHighlighter */ -import '~/line_highlighter'; +import LineHighlighter from '~/line_highlighter'; (function() { describe('LineHighlighter', function() { diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js index 70ae63ba036..2f02c11482f 100644 --- a/spec/javascripts/merge_request_spec.js +++ b/spec/javascripts/merge_request_spec.js @@ -1,7 +1,6 @@ /* eslint-disable space-before-function-paren, no-return-assign */ -/* global MergeRequest */ -import '~/merge_request'; +import MergeRequest from '~/merge_request'; import CloseReopenReportToggle from '~/close_reopen_report_toggle'; import IssuablesHelper from '~/helpers/issuables_helper'; diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js index 72790eb215a..3267e29585b 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -1,8 +1,7 @@ /* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, max-len */ -/* global Sidebar */ import '~/commons/bootstrap'; -import '~/right_sidebar'; +import Sidebar from '~/right_sidebar'; (function() { var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState; -- cgit v1.2.1 From cba40a1f551e4c1b46bfa49a709f59feb59782bd Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Thu, 7 Dec 2017 19:56:59 -0200 Subject: Stop sending milestone and labels data over the wire for MR widget requests --- .../projects/merge_requests_controller_spec.rb | 8 +- .../merge_requests/mini_pipeline_graph_spec.rb | 8 +- .../api/schemas/entities/merge_request.json | 105 -------------- .../api/schemas/entities/merge_request_widget.json | 105 ++++++++++++++ spec/serializers/merge_request_entity_spec.rb | 157 --------------------- spec/serializers/merge_request_serializer_spec.rb | 48 ++++--- .../merge_request_widget_entity_spec.rb | 118 ++++++++++++++++ 7 files changed, 258 insertions(+), 291 deletions(-) delete mode 100644 spec/fixtures/api/schemas/entities/merge_request.json create mode 100644 spec/fixtures/api/schemas/entities/merge_request_widget.json delete mode 100644 spec/serializers/merge_request_entity_spec.rb create mode 100644 spec/serializers/merge_request_widget_entity_spec.rb (limited to 'spec') diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 51d5d6a52b3..d03ecefe47f 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -91,11 +91,11 @@ describe Projects::MergeRequestsController do end end - context 'without basic serializer param' do - it 'renders the merge request in the json format' do - go(format: :json) + context 'with widget serializer param' do + it 'renders widget MR entity as json' do + go(serializer: 'widget', format: :json) - expect(response).to match_response_schema('entities/merge_request') + expect(response).to match_response_schema('entities/merge_request_widget') end end end diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index 93c5e945453..a7e7c0eeff6 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -15,8 +15,8 @@ feature 'Mini Pipeline Graph', :js do visit_merge_request end - def visit_merge_request(format = :html) - visit project_merge_request_path(project, merge_request, format: format) + def visit_merge_request(format: :html, serializer: nil) + visit project_merge_request_path(project, merge_request, format: format, serializer: serializer) end it 'should display a mini pipeline graph' do @@ -33,12 +33,12 @@ feature 'Mini Pipeline Graph', :js do end it 'avoids repeated database queries' do - before = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) } + before = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } create(:ci_build, pipeline: pipeline, legacy_artifacts_file: artifacts_file2) create(:ci_build, pipeline: pipeline, when: 'manual') - after = ActiveRecord::QueryRecorder.new { visit_merge_request(:json) } + after = ActiveRecord::QueryRecorder.new { visit_merge_request(format: :json, serializer: 'widget') } expect(before.count).to eq(after.count) expect(before.cached_count).to eq(after.cached_count) diff --git a/spec/fixtures/api/schemas/entities/merge_request.json b/spec/fixtures/api/schemas/entities/merge_request.json deleted file mode 100644 index ba094ba1657..00000000000 --- a/spec/fixtures/api/schemas/entities/merge_request.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "type": "object", - "properties" : { - "id": { "type": "integer" }, - "iid": { "type": "integer" }, - "author_id": { "type": "integer" }, - "description": { "type": ["string", "null"] }, - "lock_version": { "type": ["string", "null"] }, - "milestone_id": { "type": ["string", "null"] }, - "position": { "type": "integer" }, - "state": { "type": "string" }, - "title": { "type": "string" }, - "updated_by_id": { "type": ["string", "null"] }, - "created_at": { "type": "string" }, - "updated_at": { "type": "string" }, - "deleted_at": { "type": ["string", "null"] }, - "time_estimate": { "type": "integer" }, - "total_time_spent": { "type": "integer" }, - "human_time_estimate": { "type": ["integer", "null"] }, - "human_total_time_spent": { "type": ["integer", "null"] }, - "milestone": { "type": ["object", "null"] }, - "labels": { "type": ["array", "null"] }, - "in_progress_merge_commit_sha": { "type": ["string", "null"] }, - "merge_error": { "type": ["string", "null"] }, - "merge_commit_sha": { "type": ["string", "null"] }, - "merge_params": { "type": ["object", "null"] }, - "merge_status": { "type": "string" }, - "merge_user_id": { "type": ["integer", "null"] }, - "merge_when_pipeline_succeeds": { "type": "boolean" }, - "source_branch": { "type": "string" }, - "source_project_id": { "type": "integer" }, - "target_branch": { "type": "string" }, - "target_project_id": { "type": "integer" }, - "merge_event": { "type": ["object", "null"] }, - "closed_event": { "type": ["object", "null"] }, - "author": { "type": ["object", "null"] }, - "merge_user": { "type": ["object", "null"] }, - "diff_head_sha": { "type": ["string", "null"] }, - "diff_head_commit_short_id": { "type": ["string", "null"] }, - "merge_commit_message": { "type": ["string", "null"] }, - "pipeline": { "type": ["object", "null"] }, - "work_in_progress": { "type": "boolean" }, - "source_branch_exists": { "type": "boolean" }, - "mergeable_discussions_state": { "type": "boolean" }, - "conflicts_can_be_resolved_in_ui": { "type": "boolean" }, - "branch_missing": { "type": "boolean" }, - "has_conflicts": { "type": "boolean" }, - "can_be_merged": { "type": "boolean" }, - "mergeable": { "type": "boolean" }, - "project_archived": { "type": "boolean" }, - "only_allow_merge_if_pipeline_succeeds": { "type": "boolean" }, - "has_ci": { "type": "boolean" }, - "ci_status": { "type": ["string", "null"] }, - "issues_links": { - "type": "object", - "required": ["closing", "mentioned_but_not_closing", "assign_to_closing"], - "properties" : { - "closing": { "type": "string" }, - "mentioned_but_not_closing": { "type": "string" }, - "assign_to_closing": { "type": ["string", "null"] } - }, - "additionalProperties": false - }, - "source_branch_with_namespace_link": { "type": "string" }, - "current_user": { - "type": "object", - "required": [ - "can_remove_source_branch", - "can_revert_on_current_merge_request", - "can_cherry_pick_on_current_merge_request" - ], - "properties": { - "can_remove_source_branch": { "type": "boolean" }, - "can_revert_on_current_merge_request": { "type": ["boolean", "null"] }, - "can_cherry_pick_on_current_merge_request": { "type": ["boolean", "null"] } - }, - "additionalProperties": false - }, - "target_branch_commits_path": { "type": "string" }, - "target_branch_tree_path": { "type": "string" }, - "source_branch_path": { "type": "string" }, - "conflict_resolution_path": { "type": ["string", "null"] }, - "cancel_merge_when_pipeline_succeeds_path": { "type": "string" }, - "create_issue_to_resolve_discussions_path": { "type": "string" }, - "merge_path": { "type": "string" }, - "cherry_pick_in_fork_path": { "type": ["string", "null"] }, - "revert_in_fork_path": { "type": ["string", "null"] }, - "email_patches_path": { "type": "string" }, - "plain_diff_path": { "type": "string" }, - "status_path": { "type": "string" }, - "new_blob_path": { "type": "string" }, - "merge_check_path": { "type": "string" }, - "ci_environments_status_path": { "type": "string" }, - "merge_commit_message_with_description": { "type": "string" }, - "diverged_commits_count": { "type": "integer" }, - "commit_change_content_path": { "type": "string" }, - "remove_wip_path": { "type": ["string", "null"] }, - "commits_count": { "type": "integer" }, - "remove_source_branch": { "type": ["boolean", "null"] }, - "merge_ongoing": { "type": "boolean" }, - "ff_only_enabled": { "type": ["boolean", false] }, - "should_be_rebased": { "type": "boolean" } - }, - "additionalProperties": false -} diff --git a/spec/fixtures/api/schemas/entities/merge_request_widget.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json new file mode 100644 index 00000000000..342890c3dee --- /dev/null +++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json @@ -0,0 +1,105 @@ +{ + "type": "object", + "properties" : { + "id": { "type": "integer" }, + "iid": { "type": "integer" }, + "author_id": { "type": "integer" }, + "description": { "type": ["string", "null"] }, + "lock_version": { "type": ["string", "null"] }, + "milestone_id": { "type": ["string", "null"] }, + "position": { "type": "integer" }, + "state": { "type": "string" }, + "title": { "type": "string" }, + "updated_by_id": { "type": ["string", "null"] }, + "created_at": { "type": "string" }, + "updated_at": { "type": "string" }, + "deleted_at": { "type": ["string", "null"] }, + "time_estimate": { "type": "integer" }, + "total_time_spent": { "type": "integer" }, + "human_time_estimate": { "type": ["integer", "null"] }, + "human_total_time_spent": { "type": ["integer", "null"] }, + "milestone": { "type": ["object", "null"] }, + "labels": { "type": ["array", "null"] }, + "in_progress_merge_commit_sha": { "type": ["string", "null"] }, + "merge_error": { "type": ["string", "null"] }, + "merge_commit_sha": { "type": ["string", "null"] }, + "merge_params": { "type": ["object", "null"] }, + "merge_status": { "type": "string" }, + "merge_user_id": { "type": ["integer", "null"] }, + "merge_when_pipeline_succeeds": { "type": "boolean" }, + "source_branch": { "type": "string" }, + "source_project_id": { "type": "integer" }, + "target_branch": { "type": "string" }, + "target_project_id": { "type": "integer" }, + "merge_event": { "type": ["object", "null"] }, + "closed_event": { "type": ["object", "null"] }, + "author": { "type": ["object", "null"] }, + "merge_user": { "type": ["object", "null"] }, + "diff_head_sha": { "type": ["string", "null"] }, + "diff_head_commit_short_id": { "type": ["string", "null"] }, + "merge_commit_message": { "type": ["string", "null"] }, + "pipeline": { "type": ["object", "null"] }, + "work_in_progress": { "type": "boolean" }, + "source_branch_exists": { "type": "boolean" }, + "mergeable_discussions_state": { "type": "boolean" }, + "conflicts_can_be_resolved_in_ui": { "type": "boolean" }, + "branch_missing": { "type": "boolean" }, + "has_conflicts": { "type": "boolean" }, + "can_be_merged": { "type": "boolean" }, + "mergeable": { "type": "boolean" }, + "project_archived": { "type": "boolean" }, + "only_allow_merge_if_pipeline_succeeds": { "type": "boolean" }, + "has_ci": { "type": "boolean" }, + "ci_status": { "type": ["string", "null"] }, + "issues_links": { + "type": "object", + "required": ["closing", "mentioned_but_not_closing", "assign_to_closing"], + "properties" : { + "closing": { "type": "string" }, + "mentioned_but_not_closing": { "type": "string" }, + "assign_to_closing": { "type": ["string", "null"] } + }, + "additionalProperties": false + }, + "source_branch_with_namespace_link": { "type": "string" }, + "current_user": { + "type": "object", + "required": [ + "can_remove_source_branch", + "can_revert_on_current_merge_request", + "can_cherry_pick_on_current_merge_request" + ], + "properties": { + "can_remove_source_branch": { "type": "boolean" }, + "can_revert_on_current_merge_request": { "type": ["boolean", "null"] }, + "can_cherry_pick_on_current_merge_request": { "type": ["boolean", "null"] } + }, + "additionalProperties": false + }, + "target_branch_commits_path": { "type": "string" }, + "target_branch_tree_path": { "type": "string" }, + "source_branch_path": { "type": "string" }, + "conflict_resolution_path": { "type": ["string", "null"] }, + "cancel_merge_when_pipeline_succeeds_path": { "type": ["string", "null"] }, + "create_issue_to_resolve_discussions_path": { "type": ["string", "null"] }, + "merge_path": { "type": ["string", "null"] }, + "cherry_pick_in_fork_path": { "type": ["string", "null"] }, + "revert_in_fork_path": { "type": ["string", "null"] }, + "email_patches_path": { "type": "string" }, + "plain_diff_path": { "type": "string" }, + "status_path": { "type": "string" }, + "new_blob_path": { "type": ["string", "null"] }, + "merge_check_path": { "type": "string" }, + "ci_environments_status_path": { "type": "string" }, + "merge_commit_message_with_description": { "type": "string" }, + "diverged_commits_count": { "type": "integer" }, + "commit_change_content_path": { "type": "string" }, + "remove_wip_path": { "type": ["string", "null"] }, + "commits_count": { "type": "integer" }, + "remove_source_branch": { "type": ["boolean", "null"] }, + "merge_ongoing": { "type": "boolean" }, + "ff_only_enabled": { "type": ["boolean", false] }, + "should_be_rebased": { "type": "boolean" } + }, + "additionalProperties": false +} diff --git a/spec/serializers/merge_request_entity_spec.rb b/spec/serializers/merge_request_entity_spec.rb deleted file mode 100644 index 1ad672fd355..00000000000 --- a/spec/serializers/merge_request_entity_spec.rb +++ /dev/null @@ -1,157 +0,0 @@ -require 'spec_helper' - -describe MergeRequestEntity do - let(:project) { create :project, :repository } - let(:resource) { create(:merge_request, source_project: project, target_project: project) } - let(:user) { create(:user) } - - let(:request) { double('request', current_user: user, project: project) } - - subject do - described_class.new(resource, request: request).as_json - end - - describe 'pipeline' do - let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) } - - context 'when is up to date' do - let(:req) { double('request', current_user: user, project: project) } - - it 'returns pipeline' do - pipeline_payload = PipelineDetailsEntity - .represent(pipeline, request: req) - .as_json - - expect(subject[:pipeline]).to eq(pipeline_payload) - end - end - - context 'when is not up to date' do - it 'returns nil' do - pipeline.update(sha: "not up to date") - - expect(subject[:pipeline]).to be_nil - end - end - end - - it 'includes issues_links' do - issues_links = subject[:issues_links] - - expect(issues_links).to include(:closing, :mentioned_but_not_closing, - :assign_to_closing) - end - - it 'has Issuable attributes' do - expect(subject).to include(:id, :iid, :author_id, :description, :lock_version, :milestone_id, - :title, :updated_by_id, :created_at, :updated_at, :milestone, :labels) - end - - it 'has time estimation attributes' do - expect(subject).to include(:time_estimate, :total_time_spent, :human_time_estimate, :human_total_time_spent) - end - - it 'has important MergeRequest attributes' do - expect(subject).to include(:state, :deleted_at, :diff_head_sha, :merge_commit_message, - :has_conflicts, :has_ci, :merge_path, - :conflict_resolution_path, - :cancel_merge_when_pipeline_succeeds_path, - :create_issue_to_resolve_discussions_path, - :source_branch_path, :target_branch_commits_path, - :target_branch_tree_path, :commits_count, :merge_ongoing, - :ff_only_enabled) - end - - it 'has email_patches_path' do - expect(subject[:email_patches_path]) - .to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.patch") - end - - it 'has plain_diff_path' do - expect(subject[:plain_diff_path]) - .to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.diff") - end - - it 'has merge_commit_message_with_description' do - expect(subject[:merge_commit_message_with_description]) - .to eq(resource.merge_commit_message(include_description: true)) - end - - describe 'new_blob_path' do - context 'when user can push to project' do - it 'returns path' do - project.add_developer(user) - - expect(subject[:new_blob_path]) - .to eq("/#{resource.project.full_path}/new/#{resource.source_branch}") - end - end - - context 'when user cannot push to project' do - it 'returns nil' do - expect(subject[:new_blob_path]).to be_nil - end - end - end - - describe 'diff_head_sha' do - before do - allow(resource).to receive(:diff_head_sha) { 'sha' } - end - - context 'when no diff head commit' do - it 'returns nil' do - allow(resource).to receive(:diff_head_commit) { nil } - - expect(subject[:diff_head_sha]).to be_nil - end - end - - context 'when diff head commit present' do - it 'returns diff head commit short id' do - allow(resource).to receive(:diff_head_commit) { double } - - expect(subject[:diff_head_sha]).to eq('sha') - end - end - end - - it 'includes merge_event' do - create(:event, :merged, author: user, project: resource.project, target: resource) - - expect(subject[:merge_event]).to include(:author, :updated_at) - end - - it 'includes closed_event' do - create(:event, :closed, author: user, project: resource.project, target: resource) - - expect(subject[:closed_event]).to include(:author, :updated_at) - end - - describe 'diverged_commits_count' do - context 'when MR open and its diverging' do - it 'returns diverged commits count' do - allow(resource).to receive_messages(open?: true, diverged_from_target_branch?: true, - diverged_commits_count: 10) - - expect(subject[:diverged_commits_count]).to eq(10) - end - end - - context 'when MR is not open' do - it 'returns 0' do - allow(resource).to receive_messages(open?: false) - - expect(subject[:diverged_commits_count]).to be_zero - end - end - - context 'when MR is not diverging' do - it 'returns 0' do - allow(resource).to receive_messages(open?: true, diverged_from_target_branch?: false) - - expect(subject[:diverged_commits_count]).to be_zero - end - end - end -end diff --git a/spec/serializers/merge_request_serializer_spec.rb b/spec/serializers/merge_request_serializer_spec.rb index e3abefa6d63..1ad974c774b 100644 --- a/spec/serializers/merge_request_serializer_spec.rb +++ b/spec/serializers/merge_request_serializer_spec.rb @@ -1,37 +1,43 @@ require 'spec_helper' describe MergeRequestSerializer do - let(:user) { build_stubbed(:user) } - let(:merge_request) { build_stubbed(:merge_request) } - - let(:serializer) do + let(:user) { create(:user) } + let(:resource) { create(:merge_request) } + let(:json_entity) do described_class.new(current_user: user) + .represent(resource, serializer: serializer) + .with_indifferent_access end - describe '#represent' do - let(:opts) { { serializer: serializer_entity } } - subject { serializer.represent(merge_request, serializer: serializer_entity) } + context 'widget merge request serialization' do + let(:serializer) { 'widget' } - context 'when passing basic serializer param' do - let(:serializer_entity) { 'basic' } + it 'matches issue json schema' do + expect(json_entity).to match_schema('entities/merge_request_widget') + end + end - it 'calls super class #represent with correct params' do - expect_any_instance_of(BaseSerializer).to receive(:represent) - .with(merge_request, opts, MergeRequestBasicEntity) + context 'sidebar merge request serialization' do + let(:serializer) { 'sidebar' } - subject - end + it 'matches basic merge request json schema' do + expect(json_entity).to match_schema('entities/merge_request_basic') end + end - context 'when serializer param is falsy' do - let(:serializer_entity) { nil } + context 'basic merge request serialization' do + let(:serializer) { 'basic' } + + it 'matches basic merge request json schema' do + expect(json_entity).to match_schema('entities/merge_request_basic') + end + end - it 'calls super class #represent with correct params' do - expect_any_instance_of(BaseSerializer).to receive(:represent) - .with(merge_request, opts, MergeRequestEntity) + context 'no serializer' do + let(:serializer) { nil } - subject - end + it 'raises an error' do + expect { json_entity }.to raise_error(NoMethodError) end end end diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb new file mode 100644 index 00000000000..a5924a8589c --- /dev/null +++ b/spec/serializers/merge_request_widget_entity_spec.rb @@ -0,0 +1,118 @@ +require 'spec_helper' + +describe MergeRequestWidgetEntity do + let(:project) { create :project, :repository } + let(:resource) { create(:merge_request, source_project: project, target_project: project) } + let(:user) { create(:user) } + + let(:request) { double('request', current_user: user, project: project) } + + subject do + described_class.new(resource, request: request).as_json + end + + describe 'pipeline' do + let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.source_branch, sha: resource.source_branch_sha, head_pipeline_of: resource) } + + context 'when is up to date' do + let(:req) { double('request', current_user: user, project: project) } + + it 'returns pipeline' do + pipeline_payload = PipelineDetailsEntity + .represent(pipeline, request: req) + .as_json + + expect(subject[:pipeline]).to eq(pipeline_payload) + end + end + + context 'when is not up to date' do + it 'returns nil' do + pipeline.update(sha: "not up to date") + + expect(subject[:pipeline]).to be_nil + end + end + end + + it 'has email_patches_path' do + expect(subject[:email_patches_path]) + .to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.patch") + end + + it 'has plain_diff_path' do + expect(subject[:plain_diff_path]) + .to eq("/#{resource.project.full_path}/merge_requests/#{resource.iid}.diff") + end + + it 'has merge_commit_message_with_description' do + expect(subject[:merge_commit_message_with_description]) + .to eq(resource.merge_commit_message(include_description: true)) + end + + describe 'new_blob_path' do + context 'when user can push to project' do + it 'returns path' do + project.add_developer(user) + + expect(subject[:new_blob_path]) + .to eq("/#{resource.project.full_path}/new/#{resource.source_branch}") + end + end + + context 'when user cannot push to project' do + it 'returns nil' do + expect(subject[:new_blob_path]).to be_nil + end + end + end + + describe 'diff_head_sha' do + before do + allow(resource).to receive(:diff_head_sha) { 'sha' } + end + + context 'when no diff head commit' do + it 'returns nil' do + allow(resource).to receive(:diff_head_commit) { nil } + + expect(subject[:diff_head_sha]).to be_nil + end + end + + context 'when diff head commit present' do + it 'returns diff head commit short id' do + allow(resource).to receive(:diff_head_commit) { double } + + expect(subject[:diff_head_sha]).to eq('sha') + end + end + end + + describe 'diverged_commits_count' do + context 'when MR open and its diverging' do + it 'returns diverged commits count' do + allow(resource).to receive_messages(open?: true, diverged_from_target_branch?: true, + diverged_commits_count: 10) + + expect(subject[:diverged_commits_count]).to eq(10) + end + end + + context 'when MR is not open' do + it 'returns 0' do + allow(resource).to receive_messages(open?: false) + + expect(subject[:diverged_commits_count]).to be_zero + end + end + + context 'when MR is not diverging' do + it 'returns 0' do + allow(resource).to receive_messages(open?: true, diverged_from_target_branch?: false) + + expect(subject[:diverged_commits_count]).to be_zero + end + end + end +end -- cgit v1.2.1 From 7edbc0f8c8aa53a385353740ea6767bc48df4def Mon Sep 17 00:00:00 2001 From: Christiaan Van den Poel Date: Mon, 18 Dec 2017 09:13:46 +0000 Subject: Fix job count in pipeline success mail --- spec/features/projects/pipelines/pipeline_spec.rb | 4 ++-- spec/models/ci/pipeline_spec.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 888e290292b..3987cea0b4f 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -152,7 +152,7 @@ describe 'Pipeline', :js do end it 'shows counter in Jobs tab' do - expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s) + expect(page.find('.js-builds-counter').text).to eq(pipeline.total_size.to_s) end it 'shows Pipeline tab as active' do @@ -248,7 +248,7 @@ describe 'Pipeline', :js do end it 'shows counter in Jobs tab' do - expect(page.find('.js-builds-counter').text).to eq(pipeline.statuses.count.to_s) + expect(page.find('.js-builds-counter').text).to eq(pipeline.total_size.to_s) end it 'shows Jobs tab as active' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 856e17b20bd..a1f63a2534b 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -1530,4 +1530,16 @@ describe Ci::Pipeline, :mailer do expect(query_count).to eq(1) end end + + describe '#total_size' do + let!(:build_job1) { create(:ci_build, pipeline: pipeline, stage_idx: 0) } + let!(:build_job2) { create(:ci_build, pipeline: pipeline, stage_idx: 0) } + let!(:test_job_failed_and_retried) { create(:ci_build, :failed, :retried, pipeline: pipeline, stage_idx: 1) } + let!(:second_test_job) { create(:ci_build, pipeline: pipeline, stage_idx: 1) } + let!(:deploy_job) { create(:ci_build, pipeline: pipeline, stage_idx: 2) } + + it 'returns all jobs (including failed and retried)' do + expect(pipeline.total_size).to eq(5) + end + end end -- cgit v1.2.1 From 4f73e14f2c30c907d4ead31dd8034aea37f14544 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Mon, 11 Dec 2017 13:25:49 +0100 Subject: Add createDateTimeFormat to format dates based on locale --- spec/javascripts/locale/index_spec.js | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 spec/javascripts/locale/index_spec.js (limited to 'spec') diff --git a/spec/javascripts/locale/index_spec.js b/spec/javascripts/locale/index_spec.js new file mode 100644 index 00000000000..0f685c6d69d --- /dev/null +++ b/spec/javascripts/locale/index_spec.js @@ -0,0 +1,43 @@ +import { createDateTimeFormat, languageCode } from '~/locale'; + +const setLanguage = (languageCode) => { + const htmlElement = document.querySelector('html'); + + if (languageCode) { + htmlElement.setAttribute('lang', languageCode); + } else { + htmlElement.removeAttribute('lang'); + } +}; + +describe('locale', () => { + afterEach(() => { + setLanguage(null); + }); + + describe('languageCode', () => { + it('parses the lang attribute', () => { + setLanguage('ja'); + + expect(languageCode()).toBe('ja'); + }); + + it('falls back to English', () => { + setLanguage(null); + + expect(languageCode()).toBe('en'); + }); + }); + + describe('createDateTimeFormat', () => { + beforeEach(() => { + setLanguage('de'); + }); + + it('creates an instance of Intl.DateTimeFormat', () => { + const dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' }); + + expect(dateFormat.format(new Date(2015, 6, 3))).toBe('3. Juli 2015'); + }); + }); +}); -- cgit v1.2.1 From 1109a5cea46b25b3bd27b095c5fd11881d88bd72 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Tue, 12 Dec 2017 12:39:31 +0100 Subject: Move dateTickFormat to separate module --- spec/javascripts/helpers/locale_helper.js | 11 +++++++ spec/javascripts/lib/utils/tick_formats_spec.js | 40 +++++++++++++++++++++++++ spec/javascripts/locale/index_spec.js | 10 +------ 3 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 spec/javascripts/helpers/locale_helper.js create mode 100644 spec/javascripts/lib/utils/tick_formats_spec.js (limited to 'spec') diff --git a/spec/javascripts/helpers/locale_helper.js b/spec/javascripts/helpers/locale_helper.js new file mode 100644 index 00000000000..99e6ce61234 --- /dev/null +++ b/spec/javascripts/helpers/locale_helper.js @@ -0,0 +1,11 @@ +/* eslint-disable import/prefer-default-export */ + +export const setLanguage = (languageCode) => { + const htmlElement = document.querySelector('html'); + + if (languageCode) { + htmlElement.setAttribute('lang', languageCode); + } else { + htmlElement.removeAttribute('lang'); + } +}; diff --git a/spec/javascripts/lib/utils/tick_formats_spec.js b/spec/javascripts/lib/utils/tick_formats_spec.js new file mode 100644 index 00000000000..283989b4fc8 --- /dev/null +++ b/spec/javascripts/lib/utils/tick_formats_spec.js @@ -0,0 +1,40 @@ +import { dateTickFormat, initDateFormats } from '~/lib/utils/tick_formats'; + +import { setLanguage } from '../../helpers/locale_helper'; + +describe('tick formats', () => { + describe('dateTickFormat', () => { + beforeAll(() => { + setLanguage('de'); + initDateFormats(); + }); + + afterAll(() => { + setLanguage(null); + }); + + it('returns year for first of January', () => { + const tick = dateTickFormat(new Date('2001-01-01')); + + expect(tick).toBe('2001'); + }); + + it('returns month for first of February', () => { + const tick = dateTickFormat(new Date('2001-02-01')); + + expect(tick).toBe('Februar'); + }); + + it('returns day and month for second of February', () => { + const tick = dateTickFormat(new Date('2001-02-02')); + + expect(tick).toBe('2. Feb.'); + }); + + it('ignores time', () => { + const tick = dateTickFormat(new Date('2001-02-02 12:34:56')); + + expect(tick).toBe('2. Feb.'); + }); + }); +}); diff --git a/spec/javascripts/locale/index_spec.js b/spec/javascripts/locale/index_spec.js index 0f685c6d69d..29b0b21eed7 100644 --- a/spec/javascripts/locale/index_spec.js +++ b/spec/javascripts/locale/index_spec.js @@ -1,14 +1,6 @@ import { createDateTimeFormat, languageCode } from '~/locale'; -const setLanguage = (languageCode) => { - const htmlElement = document.querySelector('html'); - - if (languageCode) { - htmlElement.setAttribute('lang', languageCode); - } else { - htmlElement.removeAttribute('lang'); - } -}; +import { setLanguage } from '../helpers/locale_helper'; describe('locale', () => { afterEach(() => { -- cgit v1.2.1 From e720e8b8fbc9c7e04e528a54cce37d18c776d2d2 Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Mon, 11 Dec 2017 14:39:33 +0100 Subject: Translate date ranges on contributors page --- .../graphs/stat_graph_contributors_spec.js | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 spec/javascripts/graphs/stat_graph_contributors_spec.js (limited to 'spec') diff --git a/spec/javascripts/graphs/stat_graph_contributors_spec.js b/spec/javascripts/graphs/stat_graph_contributors_spec.js new file mode 100644 index 00000000000..962423462e7 --- /dev/null +++ b/spec/javascripts/graphs/stat_graph_contributors_spec.js @@ -0,0 +1,26 @@ +import ContributorsStatGraph from '~/graphs/stat_graph_contributors'; +import { ContributorsGraph } from '~/graphs/stat_graph_contributors_graph'; + +import { setLanguage } from '../helpers/locale_helper'; + +describe('ContributorsStatGraph', () => { + describe('change_date_header', () => { + beforeAll(() => { + setLanguage('de'); + }); + + afterAll(() => { + setLanguage(null); + }); + + it('uses the locale to display date ranges', () => { + ContributorsGraph.init_x_domain([{ date: '2013-01-31' }, { date: '2012-01-31' }]); + setFixtures('
'); + const graph = new ContributorsStatGraph(); + + graph.change_date_header(); + + expect(document.getElementById('date_header').innerText).toBe('31. Januar 2012 – 31. Januar 2013'); + }); + }); +}); -- cgit v1.2.1 From 48cb9fa8104c3b001856ebc0521bb52e0a6d7739 Mon Sep 17 00:00:00 2001 From: Stanislaw Wozniak Date: Mon, 18 Dec 2017 11:15:41 +0000 Subject: Fixes 40842 - Adds extra cookies to JIRA service requests --- spec/models/project_services/jira_service_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index ad22fb2a386..c9b3c6cf602 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -395,6 +395,26 @@ describe JiraService do end end + describe 'additional cookies' do + let(:project) { create(:project) } + + context 'provides additional cookies to allow basic auth with oracle webgate' do + before do + @service = project.create_jira_service( + active: true, properties: { url: 'http://jira.com' }) + end + + after do + @service.destroy! + end + + it 'is initialized' do + expect(@service.options[:use_cookies]).to eq(true) + expect(@service.options[:additional_cookies]).to eq(["OBBasicAuth=fromDialog"]) + end + end + end + describe 'project and issue urls' do let(:project) { create(:project) } -- cgit v1.2.1 From ef454f68e837e4e7360fe1518686dd56adbbb0a9 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 8 Dec 2017 12:17:22 +0000 Subject: Reset todo counters when the target is deleted When the target is deleted, todos are destroyed, but we did not reset the todo cache for users with todos on the deleted target. This would only update after the next time the todo cache was updated for that user. --- .../controllers/projects/issues_controller_spec.rb | 2 +- .../projects/merge_requests_controller_spec.rb | 2 +- spec/services/issuable/destroy_service_spec.rb | 16 ++++++++++++++- spec/services/notes/destroy_service_spec.rb | 16 ++++++++++++--- spec/services/todo_service_spec.rb | 23 ++++++++++++++++++---- 5 files changed, 49 insertions(+), 10 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb index 4dbbaecdd6d..b7447f654c4 100644 --- a/spec/controllers/projects/issues_controller_spec.rb +++ b/spec/controllers/projects/issues_controller_spec.rb @@ -861,7 +861,7 @@ describe Projects::IssuesController do end it 'delegates the update of the todos count cache to TodoService' do - expect_any_instance_of(TodoService).to receive(:destroy_issuable).with(issue, owner).once + expect_any_instance_of(TodoService).to receive(:destroy_target).with(issue).once delete :destroy, namespace_id: project.namespace, project_id: project, id: issue.iid end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 51d5d6a52b3..97a5018d714 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -468,7 +468,7 @@ describe Projects::MergeRequestsController do end it 'delegates the update of the todos count cache to TodoService' do - expect_any_instance_of(TodoService).to receive(:destroy_issuable).with(merge_request, owner).once + expect_any_instance_of(TodoService).to receive(:destroy_target).with(merge_request).once delete :destroy, namespace_id: project.namespace, project_id: project, id: merge_request.iid end diff --git a/spec/services/issuable/destroy_service_spec.rb b/spec/services/issuable/destroy_service_spec.rb index d74d98c6079..0a3647a814f 100644 --- a/spec/services/issuable/destroy_service_spec.rb +++ b/spec/services/issuable/destroy_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Issuable::DestroyService do let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project, :public) } subject(:service) { described_class.new(project, user) } @@ -19,6 +19,13 @@ describe Issuable::DestroyService do service.execute(issue) end + + it 'updates the todo caches for users with todos on the issue' do + create(:todo, target: issue, user: user, author: user, project: project) + + expect { service.execute(issue) } + .to change { user.todos_pending_count }.from(1).to(0) + end end context 'when issuable is a merge request' do @@ -33,6 +40,13 @@ describe Issuable::DestroyService do service.execute(merge_request) end + + it 'updates the todo caches for users with todos on the merge request' do + create(:todo, target: merge_request, user: user, author: user, project: project) + + expect { service.execute(merge_request) } + .to change { user.todos_pending_count }.from(1).to(0) + end end end end diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb index c9a99a43edb..64445be560e 100644 --- a/spec/services/notes/destroy_service_spec.rb +++ b/spec/services/notes/destroy_service_spec.rb @@ -1,15 +1,25 @@ require 'spec_helper' describe Notes::DestroyService do + set(:project) { create(:project, :public) } + set(:issue) { create(:issue, project: project) } + let(:user) { issue.author } + describe '#execute' do it 'deletes a note' do - project = create(:project) - issue = create(:issue, project: project) note = create(:note, project: project, noteable: issue) - described_class.new(project, note.author).execute(note) + described_class.new(project, user).execute(note) expect(project.issues.find(issue.id).notes).not_to include(note) end + + it 'updates the todo counts for users with todos for the note' do + note = create(:note, project: project, noteable: issue) + create(:todo, note: note, target: issue, user: user, author: user, project: project) + + expect { described_class.new(project, user).execute(note) } + .to change { user.todos_pending_count }.from(1).to(0) + end end end diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb index dc2673abc73..88013acae0a 100644 --- a/spec/services/todo_service_spec.rb +++ b/spec/services/todo_service_spec.rb @@ -248,11 +248,26 @@ describe TodoService do end end - describe '#destroy_issuable' do - it 'refresh the todos count cache for the user' do - expect(john_doe).to receive(:update_todos_count_cache).and_call_original + describe '#destroy_target' do + it 'refreshes the todos count cache for users with todos on the target' do + create(:todo, target: issue, user: john_doe, author: john_doe, project: issue.project) - service.destroy_issuable(issue, john_doe) + expect_any_instance_of(User).to receive(:update_todos_count_cache).and_call_original + + service.destroy_target(issue) { } + end + + it 'does not refresh the todos count cache for users with only done todos on the target' do + create(:todo, :done, target: issue, user: john_doe, author: john_doe, project: issue.project) + + expect_any_instance_of(User).not_to receive(:update_todos_count_cache) + + service.destroy_target(issue) { } + end + + it 'yields the target to the caller' do + expect { |b| service.destroy_target(issue, &b) } + .to yield_with_args(issue) end end -- cgit v1.2.1 From c77083a4938b42e1901a4cb69106a39a04f5c30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mica=C3=ABl=20Bergeron?= Date: Mon, 18 Dec 2017 10:21:33 -0500 Subject: fix the commit diff discussion sending the wrong url it should now send you to the merge request diff path scoped to the commit. --- spec/helpers/notes_helper_spec.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/helpers/notes_helper_spec.rb b/spec/helpers/notes_helper_spec.rb index cd15e27b497..36a44f8567a 100644 --- a/spec/helpers/notes_helper_spec.rb +++ b/spec/helpers/notes_helper_spec.rb @@ -41,6 +41,7 @@ describe NotesHelper do describe '#discussion_path' do let(:project) { create(:project, :repository) } + let(:anchor) { discussion.line_code } context 'for a merge request discusion' do let(:merge_request) { create(:merge_request, source_project: project, target_project: project, importing: true) } @@ -151,6 +152,15 @@ describe NotesHelper do expect(helper.discussion_path(discussion)).to be_nil end end + + context 'for a contextual commit discussion' do + let(:commit) { merge_request.commits.last } + let(:discussion) { create(:diff_note_on_merge_request, noteable: merge_request, project: project, commit_id: commit.id).to_discussion } + + it 'returns the merge request diff discussion scoped in the commit' do + expect(helper.discussion_path(discussion)).to eq(diffs_project_merge_request_path(project, merge_request, commit_id: commit.id, anchor: anchor)) + end + end end context 'for a commit discussion' do @@ -160,7 +170,7 @@ describe NotesHelper do let(:discussion) { create(:diff_note_on_commit, project: project).to_discussion } it 'returns the commit path with the line code' do - expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: discussion.line_code)) + expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: anchor)) end end @@ -168,7 +178,7 @@ describe NotesHelper do let(:discussion) { create(:legacy_diff_note_on_commit, project: project).to_discussion } it 'returns the commit path with the line code' do - expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: discussion.line_code)) + expect(helper.discussion_path(discussion)).to eq(project_commit_path(project, commit, anchor: anchor)) end end -- cgit v1.2.1 From e4b72248c243d66c19e300ed88532c5c795877cd Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Mon, 18 Dec 2017 15:54:44 +0000 Subject: Only render signout screen when user is signed out --- spec/features/issues_spec.rb | 1006 +++++++++++++++++++++--------------------- 1 file changed, 515 insertions(+), 491 deletions(-) (limited to 'spec') diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 852d9e368aa..d1ff057a0c6 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -8,729 +8,753 @@ describe 'Issues' do let(:user) { create(:user) } let(:project) { create(:project, :public) } - before do - sign_in(user) - user2 = create(:user) - - project.team << [[user, user2], :developer] - end + describe 'while user is signed out' do + describe 'empty state' do + it 'user sees empty state' do + visit project_issues_path(project) - describe 'Edit issue' do - let!(:issue) do - create(:issue, - author: user, - assignees: [user], - project: project) + expect(page).to have_content('Register / Sign In') + expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.') + expect(page).to have_content('You can register or sign in to create issues for this project.') + end end + end + describe 'while user is signed in' do before do - visit edit_project_issue_path(project, issue) - find('.js-zen-enter').click - end - - it 'opens new issue popup' do - expect(page).to have_content("Issue ##{issue.iid}") - end - end + sign_in(user) + user2 = create(:user) - describe 'Editing issue assignee' do - let!(:issue) do - create(:issue, - author: user, - assignees: [user], - project: project) + project.team << [[user, user2], :developer] end - it 'allows user to select unassigned', :js do - visit edit_project_issue_path(project, issue) - - expect(page).to have_content "Assignee #{user.name}" + describe 'empty state' do + it 'user sees empty state' do + visit project_issues_path(project) - first('.js-user-search').click - click_link 'Unassigned' + expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project') + expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.') + expect(page).to have_content('New issue') + end + end - click_button 'Save changes' + describe 'Edit issue' do + let!(:issue) do + create(:issue, + author: user, + assignees: [user], + project: project) + end - page.within('.assignee') do - expect(page).to have_content 'No assignee - assign yourself' + before do + visit edit_project_issue_path(project, issue) + find('.js-zen-enter').click end - expect(issue.reload.assignees).to be_empty + it 'opens new issue popup' do + expect(page).to have_content("Issue ##{issue.iid}") + end end - end - describe 'due date', :js do - context 'on new form' do - before do - visit new_project_issue_path(project) + describe 'Editing issue assignee' do + let!(:issue) do + create(:issue, + author: user, + assignees: [user], + project: project) end - it 'saves with due date' do - date = Date.today.at_beginning_of_month - - fill_in 'issue_title', with: 'bug 345' - fill_in 'issue_description', with: 'bug description' - find('#issuable-due-date').click + it 'allows user to select unassigned', :js do + visit edit_project_issue_path(project, issue) - page.within '.pika-single' do - click_button date.day - end + expect(page).to have_content "Assignee #{user.name}" - expect(find('#issuable-due-date').value).to eq date.to_s + first('.js-user-search').click + click_link 'Unassigned' - click_button 'Submit issue' + click_button 'Save changes' - page.within '.issuable-sidebar' do - expect(page).to have_content date.to_s(:medium) + page.within('.assignee') do + expect(page).to have_content 'No assignee - assign yourself' end + + expect(issue.reload.assignees).to be_empty end end - context 'on edit form' do - let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } + describe 'due date', :js do + context 'on new form' do + before do + visit new_project_issue_path(project) + end - before do - visit edit_project_issue_path(project, issue) - end + it 'saves with due date' do + date = Date.today.at_beginning_of_month - it 'saves with due date' do - date = Date.today.at_beginning_of_month + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click - expect(find('#issuable-due-date').value).to eq date.to_s + page.within '.pika-single' do + click_button date.day + end - date = date.tomorrow + expect(find('#issuable-due-date').value).to eq date.to_s - fill_in 'issue_title', with: 'bug 345' - fill_in 'issue_description', with: 'bug description' - find('#issuable-due-date').click + click_button 'Submit issue' - page.within '.pika-single' do - click_button date.day + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end end + end - expect(find('#issuable-due-date').value).to eq date.to_s + context 'on edit form' do + let(:issue) { create(:issue, author: user, project: project, due_date: Date.today.at_beginning_of_month.to_s) } - click_button 'Save changes' - - page.within '.issuable-sidebar' do - expect(page).to have_content date.to_s(:medium) + before do + visit edit_project_issue_path(project, issue) end - end - it 'warns about version conflict' do - issue.update(title: "New title") + it 'saves with due date' do + date = Date.today.at_beginning_of_month - fill_in 'issue_title', with: 'bug 345' - fill_in 'issue_description', with: 'bug description' + expect(find('#issuable-due-date').value).to eq date.to_s - click_button 'Save changes' + date = date.tomorrow - expect(page).to have_content 'Someone edited the issue the same time you did' - end - end - end + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' + find('#issuable-due-date').click + + page.within '.pika-single' do + click_button date.day + end - describe 'Issue info' do - it 'links to current issue in breadcrubs' do - issue = create(:issue, project: project) + expect(find('#issuable-due-date').value).to eq date.to_s - visit project_issue_path(project, issue) + click_button 'Save changes' - expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue)) - end + page.within '.issuable-sidebar' do + expect(page).to have_content date.to_s(:medium) + end + end - it 'excludes award_emoji from comment count' do - issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar') - create(:award_emoji, awardable: issue) + it 'warns about version conflict' do + issue.update(title: "New title") - visit project_issues_path(project, assignee_id: user.id) + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' - expect(page).to have_content 'foobar' - expect(page.all('.no-comments').first.text).to eq "0" - end - end + click_button 'Save changes' - describe 'Filter issue' do - before do - %w(foobar barbaz gitlab).each do |title| - create(:issue, - author: user, - assignees: [user], - project: project, - title: title) + expect(page).to have_content 'Someone edited the issue the same time you did' + end end - - @issue = Issue.find_by(title: 'foobar') - @issue.milestone = create(:milestone, project: project) - @issue.assignees = [] - @issue.save end - let(:issue) { @issue } + describe 'Issue info' do + it 'links to current issue in breadcrubs' do + issue = create(:issue, project: project) - it 'allows filtering by issues with no specified assignee' do - visit project_issues_path(project, assignee_id: IssuableFinder::NONE) + visit project_issue_path(project, issue) - expect(page).to have_content 'foobar' - expect(page).not_to have_content 'barbaz' - expect(page).not_to have_content 'gitlab' - end + expect(find('.breadcrumbs-sub-title a')[:href]).to end_with(issue_path(issue)) + end - it 'allows filtering by a specified assignee' do - visit project_issues_path(project, assignee_id: user.id) + it 'excludes award_emoji from comment count' do + issue = create(:issue, author: user, assignees: [user], project: project, title: 'foobar') + create(:award_emoji, awardable: issue) - expect(page).not_to have_content 'foobar' - expect(page).to have_content 'barbaz' - expect(page).to have_content 'gitlab' - end - end + visit project_issues_path(project, assignee_id: user.id) - describe 'filter issue' do - titles = %w[foo bar baz] - titles.each_with_index do |title, index| - let!(title.to_sym) do - create(:issue, title: title, - project: project, - created_at: Time.now - (index * 60)) + expect(page).to have_content 'foobar' + expect(page.all('.no-comments').first.text).to eq "0" end end - let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') } - let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } - it 'sorts by newest' do - visit project_issues_path(project, sort: sort_value_created_date) + describe 'Filter issue' do + before do + %w(foobar barbaz gitlab).each do |title| + create(:issue, + author: user, + assignees: [user], + project: project, + title: title) + end - expect(first_issue).to include('foo') - expect(last_issue).to include('baz') - end + @issue = Issue.find_by(title: 'foobar') + @issue.milestone = create(:milestone, project: project) + @issue.assignees = [] + @issue.save + end - it 'sorts by most recently updated' do - baz.updated_at = Time.now + 100 - baz.save - visit project_issues_path(project, sort: sort_value_recently_updated) + let(:issue) { @issue } - expect(first_issue).to include('baz') - end + it 'allows filtering by issues with no specified assignee' do + visit project_issues_path(project, assignee_id: IssuableFinder::NONE) - describe 'sorting by due date' do - before do - foo.update(due_date: 1.day.from_now) - bar.update(due_date: 6.days.from_now) + expect(page).to have_content 'foobar' + expect(page).not_to have_content 'barbaz' + expect(page).not_to have_content 'gitlab' end - it 'sorts by due date' do - visit project_issues_path(project, sort: sort_value_due_date) + it 'allows filtering by a specified assignee' do + visit project_issues_path(project, assignee_id: user.id) - expect(first_issue).to include('foo') + expect(page).not_to have_content 'foobar' + expect(page).to have_content 'barbaz' + expect(page).to have_content 'gitlab' end + end - it 'sorts by due date by excluding nil due dates' do - bar.update(due_date: nil) + describe 'filter issue' do + titles = %w[foo bar baz] + titles.each_with_index do |title, index| + let!(title.to_sym) do + create(:issue, title: title, + project: project, + created_at: Time.now - (index * 60)) + end + end + let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') } + let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } - visit project_issues_path(project, sort: sort_value_due_date) + it 'sorts by newest' do + visit project_issues_path(project, sort: sort_value_created_date) expect(first_issue).to include('foo') + expect(last_issue).to include('baz') end - context 'with a filter on labels' do - let(:label) { create(:label, project: project) } + it 'sorts by most recently updated' do + baz.updated_at = Time.now + 100 + baz.save + visit project_issues_path(project, sort: sort_value_recently_updated) + expect(first_issue).to include('baz') + end + + describe 'sorting by due date' do before do - create(:label_link, label: label, target: foo) + foo.update(due_date: 1.day.from_now) + bar.update(due_date: 6.days.from_now) + end + + it 'sorts by due date' do + visit project_issues_path(project, sort: sort_value_due_date) + + expect(first_issue).to include('foo') end - it 'sorts by least recently due date by excluding nil due dates' do + it 'sorts by due date by excluding nil due dates' do bar.update(due_date: nil) - visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later) + visit project_issues_path(project, sort: sort_value_due_date) expect(first_issue).to include('foo') end - end - end - describe 'filtering by due date' do - before do - foo.update(due_date: 1.day.from_now) - bar.update(due_date: 6.days.from_now) - end + context 'with a filter on labels' do + let(:label) { create(:label, project: project) } + + before do + create(:label_link, label: label, target: foo) + end + + it 'sorts by least recently due date by excluding nil due dates' do + bar.update(due_date: nil) - it 'filters by none' do - visit project_issues_path(project, due_date: Issue::NoDueDate.name) + visit project_issues_path(project, label_names: [label.name], sort: sort_value_due_date_later) - page.within '.issues-holder' do - expect(page).not_to have_content('foo') - expect(page).not_to have_content('bar') - expect(page).to have_content('baz') + expect(first_issue).to include('foo') + end end end - it 'filters by any' do - visit project_issues_path(project, due_date: Issue::AnyDueDate.name) + describe 'filtering by due date' do + before do + foo.update(due_date: 1.day.from_now) + bar.update(due_date: 6.days.from_now) + end + + it 'filters by none' do + visit project_issues_path(project, due_date: Issue::NoDueDate.name) - page.within '.issues-holder' do - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).to have_content('baz') + page.within '.issues-holder' do + expect(page).not_to have_content('foo') + expect(page).not_to have_content('bar') + expect(page).to have_content('baz') + end + end + + it 'filters by any' do + visit project_issues_path(project, due_date: Issue::AnyDueDate.name) + + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).to have_content('baz') + end end - end - it 'filters by due this week' do - foo.update(due_date: Date.today.beginning_of_week + 2.days) - bar.update(due_date: Date.today.end_of_week) - baz.update(due_date: Date.today - 8.days) + it 'filters by due this week' do + foo.update(due_date: Date.today.beginning_of_week + 2.days) + bar.update(due_date: Date.today.end_of_week) + baz.update(due_date: Date.today - 8.days) - visit project_issues_path(project, due_date: Issue::DueThisWeek.name) + visit project_issues_path(project, due_date: Issue::DueThisWeek.name) - page.within '.issues-holder' do - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).not_to have_content('baz') + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).not_to have_content('baz') + end end - end - it 'filters by due this month' do - foo.update(due_date: Date.today.beginning_of_month + 2.days) - bar.update(due_date: Date.today.end_of_month) - baz.update(due_date: Date.today - 50.days) + it 'filters by due this month' do + foo.update(due_date: Date.today.beginning_of_month + 2.days) + bar.update(due_date: Date.today.end_of_month) + baz.update(due_date: Date.today - 50.days) - visit project_issues_path(project, due_date: Issue::DueThisMonth.name) + visit project_issues_path(project, due_date: Issue::DueThisMonth.name) - page.within '.issues-holder' do - expect(page).to have_content('foo') - expect(page).to have_content('bar') - expect(page).not_to have_content('baz') + page.within '.issues-holder' do + expect(page).to have_content('foo') + expect(page).to have_content('bar') + expect(page).not_to have_content('baz') + end end - end - it 'filters by overdue' do - foo.update(due_date: Date.today + 2.days) - bar.update(due_date: Date.today + 20.days) - baz.update(due_date: Date.yesterday) + it 'filters by overdue' do + foo.update(due_date: Date.today + 2.days) + bar.update(due_date: Date.today + 20.days) + baz.update(due_date: Date.yesterday) - visit project_issues_path(project, due_date: Issue::Overdue.name) + visit project_issues_path(project, due_date: Issue::Overdue.name) - page.within '.issues-holder' do - expect(page).not_to have_content('foo') - expect(page).not_to have_content('bar') - expect(page).to have_content('baz') + page.within '.issues-holder' do + expect(page).not_to have_content('foo') + expect(page).not_to have_content('bar') + expect(page).to have_content('baz') + end end end - end - describe 'sorting by milestone' do - before do - foo.milestone = newer_due_milestone - foo.save - bar.milestone = later_due_milestone - bar.save - end + describe 'sorting by milestone' do + before do + foo.milestone = newer_due_milestone + foo.save + bar.milestone = later_due_milestone + bar.save + end - it 'sorts by milestone' do - visit project_issues_path(project, sort: sort_value_milestone) + it 'sorts by milestone' do + visit project_issues_path(project, sort: sort_value_milestone) - expect(first_issue).to include('foo') - expect(last_issue).to include('baz') + expect(first_issue).to include('foo') + expect(last_issue).to include('baz') + end end - end - describe 'combine filter and sort' do - let(:user2) { create(:user) } + describe 'combine filter and sort' do + let(:user2) { create(:user) } - before do - foo.assignees << user2 - foo.save - bar.assignees << user2 - bar.save - end + before do + foo.assignees << user2 + foo.save + bar.assignees << user2 + bar.save + end - it 'sorts with a filter applied' do - visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id) + it 'sorts with a filter applied' do + visit project_issues_path(project, sort: sort_value_created_date, assignee_id: user2.id) - expect(first_issue).to include('foo') - expect(last_issue).to include('bar') - expect(page).not_to have_content('baz') + expect(first_issue).to include('foo') + expect(last_issue).to include('bar') + expect(page).not_to have_content('baz') + end end end - end - describe 'when I want to reset my incoming email token' do - let(:project1) { create(:project, namespace: user.namespace) } - let!(:issue) { create(:issue, project: project1) } + describe 'when I want to reset my incoming email token' do + let(:project1) { create(:project, namespace: user.namespace) } + let!(:issue) { create(:issue, project: project1) } - before do - stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") - project1.team << [user, :master] - visit namespace_project_issues_path(user.namespace, project1) - end + before do + stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") + project1.team << [user, :master] + visit namespace_project_issues_path(user.namespace, project1) + end - it 'changes incoming email address token', :js do - find('.issuable-email-modal-btn').click - previous_token = find('input#issuable_email').value - find('.incoming-email-token-reset').click + it 'changes incoming email address token', :js do + find('.issuable-email-modal-btn').click + previous_token = find('input#issuable_email').value + find('.incoming-email-token-reset').click - wait_for_requests + wait_for_requests - expect(page).to have_no_field('issuable_email', with: previous_token) - new_token = project1.new_issuable_address(user.reload, 'issue') - expect(page).to have_field( - 'issuable_email', - with: new_token - ) + expect(page).to have_no_field('issuable_email', with: previous_token) + new_token = project1.new_issuable_address(user.reload, 'issue') + expect(page).to have_field( + 'issuable_email', + with: new_token + ) + end end - end - describe 'update labels from issue#show', :js do - let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } - let!(:label) { create(:label, project: project) } + describe 'update labels from issue#show', :js do + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + let!(:label) { create(:label, project: project) } - before do - visit project_issue_path(project, issue) - end + before do + visit project_issue_path(project, issue) + end - it 'will not send ajax request when no data is changed' do - page.within '.labels' do - click_link 'Edit' + it 'will not send ajax request when no data is changed' do + page.within '.labels' do + click_link 'Edit' - find('.dropdown-menu-close', match: :first).click + find('.dropdown-menu-close', match: :first).click - expect(page).not_to have_selector('.block-loading') + expect(page).not_to have_selector('.block-loading') + end end end - end - describe 'update assignee from issue#show' do - let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + describe 'update assignee from issue#show' do + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } - context 'by authorized user' do - it 'allows user to select unassigned', :js do - visit project_issue_path(project, issue) + context 'by authorized user' do + it 'allows user to select unassigned', :js do + visit project_issue_path(project, issue) - page.within('.assignee') do - expect(page).to have_content "#{user.name}" + page.within('.assignee') do + expect(page).to have_content "#{user.name}" - click_link 'Edit' - click_link 'Unassigned' - first('.title').click - expect(page).to have_content 'No assignee' - end + click_link 'Edit' + click_link 'Unassigned' + first('.title').click + expect(page).to have_content 'No assignee' + end - # wait_for_requests does not work with vue-resource at the moment - sleep 1 + # wait_for_requests does not work with vue-resource at the moment + sleep 1 - expect(issue.reload.assignees).to be_empty - end + expect(issue.reload.assignees).to be_empty + end - it 'allows user to select an assignee', :js do - issue2 = create(:issue, project: project, author: user) - visit project_issue_path(project, issue2) + it 'allows user to select an assignee', :js do + issue2 = create(:issue, project: project, author: user) + visit project_issue_path(project, issue2) - page.within('.assignee') do - expect(page).to have_content "No assignee" - end + page.within('.assignee') do + expect(page).to have_content "No assignee" + end - page.within '.assignee' do - click_link 'Edit' - end + page.within '.assignee' do + click_link 'Edit' + end - page.within '.dropdown-menu-user' do - click_link user.name - end + page.within '.dropdown-menu-user' do + click_link user.name + end - page.within('.assignee') do - expect(page).to have_content user.name + page.within('.assignee') do + expect(page).to have_content user.name + end end - end - it 'allows user to unselect themselves', :js do - issue2 = create(:issue, project: project, author: user) - visit project_issue_path(project, issue2) + it 'allows user to unselect themselves', :js do + issue2 = create(:issue, project: project, author: user) + visit project_issue_path(project, issue2) - page.within '.assignee' do - click_link 'Edit' - click_link user.name + page.within '.assignee' do + click_link 'Edit' + click_link user.name - page.within '.value .author' do - expect(page).to have_content user.name - end + page.within '.value .author' do + expect(page).to have_content user.name + end - click_link 'Edit' - click_link user.name + click_link 'Edit' + click_link user.name - page.within '.value .assign-yourself' do - expect(page).to have_content "No assignee" + page.within '.value .assign-yourself' do + expect(page).to have_content "No assignee" + end end end end - end - context 'by unauthorized user' do - let(:guest) { create(:user) } + context 'by unauthorized user' do + let(:guest) { create(:user) } - before do - project.team << [[guest], :guest] - end + before do + project.team << [[guest], :guest] + end - it 'shows assignee text', :js do - sign_out(:user) - sign_in(guest) + it 'shows assignee text', :js do + sign_out(:user) + sign_in(guest) - visit project_issue_path(project, issue) - expect(page).to have_content issue.assignees.first.name + visit project_issue_path(project, issue) + expect(page).to have_content issue.assignees.first.name + end end end - end - describe 'update milestone from issue#show' do - let!(:issue) { create(:issue, project: project, author: user) } - let!(:milestone) { create(:milestone, project: project) } + describe 'update milestone from issue#show' do + let!(:issue) { create(:issue, project: project, author: user) } + let!(:milestone) { create(:milestone, project: project) } - context 'by authorized user' do - it 'allows user to select unassigned', :js do - visit project_issue_path(project, issue) + context 'by authorized user' do + it 'allows user to select unassigned', :js do + visit project_issue_path(project, issue) - page.within('.milestone') do - expect(page).to have_content "None" - end + page.within('.milestone') do + expect(page).to have_content "None" + end - find('.block.milestone .edit-link').click - sleep 2 # wait for ajax stuff to complete - first('.dropdown-content li').click - sleep 2 - page.within('.milestone') do - expect(page).to have_content 'None' + find('.block.milestone .edit-link').click + sleep 2 # wait for ajax stuff to complete + first('.dropdown-content li').click + sleep 2 + page.within('.milestone') do + expect(page).to have_content 'None' + end + + expect(issue.reload.milestone).to be_nil end - expect(issue.reload.milestone).to be_nil - end + it 'allows user to de-select milestone', :js do + visit project_issue_path(project, issue) - it 'allows user to de-select milestone', :js do - visit project_issue_path(project, issue) + page.within('.milestone') do + click_link 'Edit' + click_link milestone.title - page.within('.milestone') do - click_link 'Edit' - click_link milestone.title - - page.within '.value' do - expect(page).to have_content milestone.title - end + page.within '.value' do + expect(page).to have_content milestone.title + end - click_link 'Edit' - click_link milestone.title + click_link 'Edit' + click_link milestone.title - page.within '.value' do - expect(page).to have_content 'None' + page.within '.value' do + expect(page).to have_content 'None' + end end end end - end - context 'by unauthorized user' do - let(:guest) { create(:user) } + context 'by unauthorized user' do + let(:guest) { create(:user) } - before do - project.team << [guest, :guest] - issue.milestone = milestone - issue.save - end + before do + project.team << [guest, :guest] + issue.milestone = milestone + issue.save + end - it 'shows milestone text', :js do - sign_out(:user) - sign_in(guest) + it 'shows milestone text', :js do + sign_out(:user) + sign_in(guest) - visit project_issue_path(project, issue) - expect(page).to have_content milestone.title + visit project_issue_path(project, issue) + expect(page).to have_content milestone.title + end end end - end - describe 'new issue' do - let!(:issue) { create(:issue, project: project) } + describe 'new issue' do + let!(:issue) { create(:issue, project: project) } - context 'by unauthenticated user' do - before do - sign_out(:user) - end + context 'by unauthenticated user' do + before do + sign_out(:user) + end - it 'redirects to signin then back to new issue after signin' do - visit project_issues_path(project) + it 'redirects to signin then back to new issue after signin' do + visit project_issues_path(project) - page.within '.nav-controls' do - click_link 'New issue' - end + page.within '.nav-controls' do + click_link 'New issue' + end - expect(current_path).to eq new_user_session_path + expect(current_path).to eq new_user_session_path - gitlab_sign_in(create(:user)) + gitlab_sign_in(create(:user)) - expect(current_path).to eq new_project_issue_path(project) + expect(current_path).to eq new_project_issue_path(project) + end end - end - context 'dropzone upload file', :js do - before do - visit new_project_issue_path(project) - end + context 'dropzone upload file', :js do + before do + visit new_project_issue_path(project) + end - it 'uploads file when dragging into textarea' do - dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + it 'uploads file when dragging into textarea' do + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') - expect(page.find_field("issue_description").value).to have_content 'banana_sample' - end + expect(page.find_field("issue_description").value).to have_content 'banana_sample' + end - it "doesn't add double newline to end of a single attachment markdown" do - dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') + it "doesn't add double newline to end of a single attachment markdown" do + dropzone_file Rails.root.join('spec', 'fixtures', 'banana_sample.gif') - expect(page.find_field("issue_description").value).not_to match /\n\n$/ - end + expect(page.find_field("issue_description").value).not_to match /\n\n$/ + end - it "cancels a file upload correctly" do - slow_requests do - dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false) + it "cancels a file upload correctly" do + slow_requests do + dropzone_file([Rails.root.join('spec', 'fixtures', 'dk.png')], 0, false) - click_button 'Cancel' - end + click_button 'Cancel' + end - expect(page).to have_button('Attach a file') - expect(page).not_to have_button('Cancel') - expect(page).not_to have_selector('.uploading-progress-container', visible: true) + expect(page).to have_button('Attach a file') + expect(page).not_to have_button('Cancel') + expect(page).not_to have_selector('.uploading-progress-container', visible: true) + end end - end - context 'form filled by URL parameters' do - let(:project) { create(:project, :public, :repository) } + context 'form filled by URL parameters' do + let(:project) { create(:project, :public, :repository) } - before do - project.repository.create_file( - user, - '.gitlab/issue_templates/bug.md', - 'this is a test "bug" template', - message: 'added issue template', - branch_name: 'master') - - visit new_project_issue_path(project, issuable_template: 'bug') - end + before do + project.repository.create_file( + user, + '.gitlab/issue_templates/bug.md', + 'this is a test "bug" template', + message: 'added issue template', + branch_name: 'master') + + visit new_project_issue_path(project, issuable_template: 'bug') + end - it 'fills in template' do - expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug') + it 'fills in template' do + expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug') + end end end - end - describe 'new issue by email' do - shared_examples 'show the email in the modal' do - let(:issue) { create(:issue, project: project) } + describe 'new issue by email' do + shared_examples 'show the email in the modal' do + let(:issue) { create(:issue, project: project) } - before do - project.issues << issue - stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") + before do + project.issues << issue + stub_incoming_email_setting(enabled: true, address: "p+%{key}@gl.ab") - visit project_issues_path(project) - click_button('Email a new issue') - end + visit project_issues_path(project) + click_button('Email a new issue') + end - it 'click the button to show modal for the new email' do - page.within '#issuable-email-modal' do - email = project.new_issuable_address(user, 'issue') + it 'click the button to show modal for the new email' do + page.within '#issuable-email-modal' do + email = project.new_issuable_address(user, 'issue') - expect(page).to have_selector("input[value='#{email}']") + expect(page).to have_selector("input[value='#{email}']") + end end end - end - context 'with existing issues' do - let!(:issue) { create(:issue, project: project, author: user) } + context 'with existing issues' do + let!(:issue) { create(:issue, project: project, author: user) } - it_behaves_like 'show the email in the modal' - end + it_behaves_like 'show the email in the modal' + end - context 'without existing issues' do - it_behaves_like 'show the email in the modal' + context 'without existing issues' do + it_behaves_like 'show the email in the modal' + end end - end - describe 'due date' do - context 'update due on issue#show', :js do - let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + describe 'due date' do + context 'update due on issue#show', :js do + let(:issue) { create(:issue, project: project, author: user, assignees: [user]) } - before do - visit project_issue_path(project, issue) - end + before do + visit project_issue_path(project, issue) + end - it 'adds due date to issue' do - date = Date.today.at_beginning_of_month + 2.days + it 'adds due date to issue' do + date = Date.today.at_beginning_of_month + 2.days - page.within '.due_date' do - click_link 'Edit' + page.within '.due_date' do + click_link 'Edit' - page.within '.pika-single' do - click_button date.day - end + page.within '.pika-single' do + click_button date.day + end - wait_for_requests + wait_for_requests - expect(find('.value').text).to have_content date.strftime('%b %-d, %Y') + expect(find('.value').text).to have_content date.strftime('%b %-d, %Y') + end end - end - it 'removes due date from issue' do - date = Date.today.at_beginning_of_month + 2.days + it 'removes due date from issue' do + date = Date.today.at_beginning_of_month + 2.days - page.within '.due_date' do - click_link 'Edit' + page.within '.due_date' do + click_link 'Edit' - page.within '.pika-single' do - click_button date.day - end + page.within '.pika-single' do + click_button date.day + end - wait_for_requests + wait_for_requests - expect(page).to have_no_content 'No due date' + expect(page).to have_no_content 'No due date' - click_link 'remove due date' - expect(page).to have_content 'No due date' + click_link 'remove due date' + expect(page).to have_content 'No due date' + end end end end - end - describe 'title issue#show', :js do - it 'updates the title', :js do - issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title') + describe 'title issue#show', :js do + it 'updates the title', :js do + issue = create(:issue, author: user, assignees: [user], project: project, title: 'new title') - visit project_issue_path(project, issue) + visit project_issue_path(project, issue) - expect(page).to have_text("new title") + expect(page).to have_text("new title") - issue.update(title: "updated title") + issue.update(title: "updated title") - wait_for_requests - expect(page).to have_text("updated title") + wait_for_requests + expect(page).to have_text("updated title") + end end - end - describe 'confidential issue#show', :js do - it 'shows confidential sibebar information as confidential and can be turned off' do - issue = create(:issue, :confidential, project: project) + describe 'confidential issue#show', :js do + it 'shows confidential sibebar information as confidential and can be turned off' do + issue = create(:issue, :confidential, project: project) - visit project_issue_path(project, issue) + visit project_issue_path(project, issue) - expect(page).to have_css('.issuable-note-warning') - expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active') - expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active') + expect(page).to have_css('.issuable-note-warning') + expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active') + expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active') - find('.confidential-edit').click - expect(page).to have_css('.sidebar-item-warning-message') + find('.confidential-edit').click + expect(page).to have_css('.sidebar-item-warning-message') - within('.sidebar-item-warning-message') do - find('.btn-close').click - end + within('.sidebar-item-warning-message') do + find('.btn-close').click + end - wait_for_requests + wait_for_requests - visit project_issue_path(project, issue) + visit project_issue_path(project, issue) - expect(page).not_to have_css('.is-active') + expect(page).not_to have_css('.is-active') + end end end end -- cgit v1.2.1 From 2ba30096d26174f22851feb8d35f287b8db772e3 Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Date: Thu, 23 Nov 2017 15:35:49 -0600 Subject: Modified contributors graph to use d3 v4 --- .../javascripts/graphs/stat_graph_contributors_graph_spec.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js index 861f26e162f..c48c587174d 100644 --- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js @@ -1,6 +1,10 @@ /* eslint-disable quotes, jasmine/no-suite-dupes, vars-on-top, no-var */ -import d3 from 'd3'; +import { + scaleLinear as d3ScaleLinear, + scaleTime as d3ScaleTime, + timeParse as d3TimeParse, +} from 'd3'; import { ContributorsGraph, ContributorsMasterGraph } from '~/graphs/stat_graph_contributors_graph'; describe("ContributorsGraph", function () { @@ -53,7 +57,7 @@ describe("ContributorsGraph", function () { it("sets the instance's x domain using the prototype's x_domain", function () { ContributorsGraph.prototype.x_domain = 20; var instance = new ContributorsGraph(); - instance.x = d3.time.scale().range([0, 100]).clamp(true); + instance.x = d3ScaleTime().range([0, 100]).clamp(true); spyOn(instance.x, 'domain'); instance.set_x_domain(); expect(instance.x.domain).toHaveBeenCalledWith(20); @@ -64,7 +68,7 @@ describe("ContributorsGraph", function () { it("sets the instance's y domain using the prototype's y_domain", function () { ContributorsGraph.prototype.y_domain = 30; var instance = new ContributorsGraph(); - instance.y = d3.scale.linear().range([100, 0]).nice(); + instance.y = d3ScaleLinear().range([100, 0]).nice(); spyOn(instance.y, 'domain'); instance.set_y_domain(); expect(instance.y.domain).toHaveBeenCalledWith(30); @@ -118,7 +122,7 @@ describe("ContributorsMasterGraph", function () { describe("#parse_dates", function () { it("parses the dates", function () { var graph = new ContributorsMasterGraph(); - var parseDate = d3.time.format("%Y-%m-%d").parse; + var parseDate = d3TimeParse("%Y-%m-%d"); var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }]; var correct = [{ date: parseDate(data[0].date) }, { date: parseDate(data[1].date) }]; graph.parse_dates(data); -- cgit v1.2.1 From 49bc458ad792a095c5ab5ebfc6b3cdf2f655bb92 Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Date: Thu, 23 Nov 2017 16:39:29 -0600 Subject: optimized d3 v4 with a custom made bundle --- spec/javascripts/graphs/stat_graph_contributors_graph_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js index c48c587174d..ead674b7735 100644 --- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js @@ -4,7 +4,7 @@ import { scaleLinear as d3ScaleLinear, scaleTime as d3ScaleTime, timeParse as d3TimeParse, -} from 'd3'; +} from '~/common_d3/index'; import { ContributorsGraph, ContributorsMasterGraph } from '~/graphs/stat_graph_contributors_graph'; describe("ContributorsGraph", function () { -- cgit v1.2.1 From be60cca90d510061a91a7be36df4c0fb6469587a Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Date: Fri, 24 Nov 2017 16:01:01 -0600 Subject: fixed specs and the non-rendering stat_graph_contributors_graph --- spec/features/calendar_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb index a9530becb65..70faf28e09d 100644 --- a/spec/features/calendar_spec.rb +++ b/spec/features/calendar_spec.rb @@ -12,7 +12,7 @@ feature 'Contributions Calendar', :js do issue_params = { title: issue_title } def get_cell_color_selector(contributions) - activity_colors = %w[#ededed #acd5f2 #7fa8c9 #527ba0 #254e77] + activity_colors = ["#ededed", "rgb(172, 213, 242)", "rgb(127, 168, 201)", "rgb(82, 123, 160)", "rgb(37, 78, 119)"] # We currently don't actually test the cases with contributions >= 20 activity_colors_index = if contributions > 0 && contributions < 10 -- cgit v1.2.1 From 4e0e2fd9d297319f323b987944b58bfd3a14ba58 Mon Sep 17 00:00:00 2001 From: Jose Ivan Vargas Date: Tue, 28 Nov 2017 13:33:17 -0600 Subject: Refactored d3 modules to instead of having a common_d3 dir, to use the micro modules instead --- .../graphs/stat_graph_contributors_graph_spec.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'spec') diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js index ead674b7735..6599839a526 100644 --- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js +++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js @@ -1,12 +1,10 @@ /* eslint-disable quotes, jasmine/no-suite-dupes, vars-on-top, no-var */ - -import { - scaleLinear as d3ScaleLinear, - scaleTime as d3ScaleTime, - timeParse as d3TimeParse, -} from '~/common_d3/index'; +import { scaleLinear, scaleTime } from 'd3-scale'; +import { timeParse } from 'd3-time-format'; import { ContributorsGraph, ContributorsMasterGraph } from '~/graphs/stat_graph_contributors_graph'; +const d3 = { scaleLinear, scaleTime, timeParse }; + describe("ContributorsGraph", function () { describe("#set_x_domain", function () { it("set the x_domain", function () { @@ -57,7 +55,7 @@ describe("ContributorsGraph", function () { it("sets the instance's x domain using the prototype's x_domain", function () { ContributorsGraph.prototype.x_domain = 20; var instance = new ContributorsGraph(); - instance.x = d3ScaleTime().range([0, 100]).clamp(true); + instance.x = d3.scaleTime().range([0, 100]).clamp(true); spyOn(instance.x, 'domain'); instance.set_x_domain(); expect(instance.x.domain).toHaveBeenCalledWith(20); @@ -68,7 +66,7 @@ describe("ContributorsGraph", function () { it("sets the instance's y domain using the prototype's y_domain", function () { ContributorsGraph.prototype.y_domain = 30; var instance = new ContributorsGraph(); - instance.y = d3ScaleLinear().range([100, 0]).nice(); + instance.y = d3.scaleLinear().range([100, 0]).nice(); spyOn(instance.y, 'domain'); instance.set_y_domain(); expect(instance.y.domain).toHaveBeenCalledWith(30); @@ -122,7 +120,7 @@ describe("ContributorsMasterGraph", function () { describe("#parse_dates", function () { it("parses the dates", function () { var graph = new ContributorsMasterGraph(); - var parseDate = d3TimeParse("%Y-%m-%d"); + var parseDate = d3.timeParse("%Y-%m-%d"); var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }]; var correct = [{ date: parseDate(data[0].date) }, { date: parseDate(data[1].date) }]; graph.parse_dates(data); -- cgit v1.2.1 From b03789395c59ce94c8bdb4e0f4806c8cd7705f46 Mon Sep 17 00:00:00 2001 From: Mario de la Ossa Date: Mon, 18 Dec 2017 22:55:51 -0600 Subject: Do not generate links for private NPM modules in blob view --- spec/models/blob_viewer/package_json_spec.rb | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'spec') diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb index 0f8330e91c1..339d4e9e644 100644 --- a/spec/models/blob_viewer/package_json_spec.rb +++ b/spec/models/blob_viewer/package_json_spec.rb @@ -22,4 +22,50 @@ describe BlobViewer::PackageJson do expect(subject.package_name).to eq('module-name') end end + + describe '#package_url' do + it 'returns the package URL' do + expect(subject).to receive(:prepare!) + + expect(subject.package_url).to eq("https://www.npmjs.com/package/#{subject.package_name}") + end + end + + describe '#package_type' do + it 'returns "package"' do + expect(subject).to receive(:prepare!) + + expect(subject.package_type).to eq('package') + end + end + + context 'when package.json has "private": true' do + let(:data) do + <<-SPEC.strip_heredoc + { + "name": "module-name", + "version": "10.3.1", + "private": true + } + SPEC + end + let(:blob) { fake_blob(path: 'package.json', data: data) } + subject { described_class.new(blob) } + + describe '#package_url' do + it 'returns nil' do + expect(subject).to receive(:prepare!) + + expect(subject.package_url).to be_nil + end + end + + describe '#package_type' do + it 'returns "private package"' do + expect(subject).to receive(:prepare!) + + expect(subject.package_type).to eq('private package') + end + end + end end -- cgit v1.2.1 From d02059ddf3fef105a8e835024b589d9eac2140f0 Mon Sep 17 00:00:00 2001 From: Mario de la Ossa Date: Mon, 18 Dec 2017 23:14:08 -0600 Subject: BlobViewer::PackageJson - if private link to homepage --- spec/models/blob_viewer/package_json_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'spec') diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb index 339d4e9e644..5ed2f4400bc 100644 --- a/spec/models/blob_viewer/package_json_spec.rb +++ b/spec/models/blob_viewer/package_json_spec.rb @@ -45,7 +45,8 @@ describe BlobViewer::PackageJson do { "name": "module-name", "version": "10.3.1", - "private": true + "private": true, + "homepage": "myawesomepackage.com" } SPEC end @@ -53,10 +54,10 @@ describe BlobViewer::PackageJson do subject { described_class.new(blob) } describe '#package_url' do - it 'returns nil' do + it 'returns homepage if any' do expect(subject).to receive(:prepare!) - expect(subject.package_url).to be_nil + expect(subject.package_url).to eq('myawesomepackage.com') end end -- cgit v1.2.1 From c6edae38870a4228e3b964d647b9ef588df11f27 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Tue, 5 Dec 2017 14:15:30 +0100 Subject: Load commit in batches for pipelines#index Uses `list_commits_by_oid` on the CommitService, to request the needed commits for pipelines. These commits are needed to display the user that created the commit and the commit title. This includes fixes for tests failing that depended on the commit being `nil`. However, now these are batch loaded, this doesn't happen anymore and the commits are an instance of BatchLoader. --- .../projects/pipelines_controller_spec.rb | 13 +++--- spec/models/commit_spec.rb | 39 ++++++++++++++++++ spec/models/repository_spec.rb | 48 ++++++++++++++++++++++ spec/serializers/pipeline_serializer_spec.rb | 6 +-- 4 files changed, 95 insertions(+), 11 deletions(-) (limited to 'spec') diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 1604a2da485..35ac999cc65 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -17,13 +17,10 @@ describe Projects::PipelinesController do describe 'GET index.json' do before do - branch_head = project.commit - parent = branch_head.parent - - create(:ci_empty_pipeline, status: 'pending', project: project, sha: branch_head.id) - create(:ci_empty_pipeline, status: 'running', project: project, sha: branch_head.id) - create(:ci_empty_pipeline, status: 'created', project: project, sha: parent.id) - create(:ci_empty_pipeline, status: 'success', project: project, sha: parent.id) + %w(pending running created success).each_with_index do |status, index| + sha = project.commit("HEAD~#{index}") + create(:ci_empty_pipeline, status: status, project: project, sha: sha) + end end subject do @@ -46,7 +43,7 @@ describe Projects::PipelinesController do context 'when performing gitaly calls', :request_store do it 'limits the Gitaly requests' do - expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(8) + expect { subject }.to change { Gitlab::GitalyClient.get_request_count }.by(3) end end end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index d18a5c9dfa6..cd955a5eb69 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -13,6 +13,45 @@ describe Commit do it { is_expected.to include_module(StaticModel) } end + describe '.lazy' do + set(:project) { create(:project, :repository) } + + context 'when the commits are found' do + let(:oids) do + %w( + 498214de67004b1da3d820901307bed2a68a8ef6 + c642fe9b8b9f28f9225d7ea953fe14e74748d53b + 6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9 + 048721d90c449b244b7b4c53a9186b04330174ec + 281d3a76f31c812dbf48abce82ccf6860adedd81 + ) + end + + subject { oids.map { |oid| described_class.lazy(project, oid) } } + + it 'batches requests for commits' do + expect(project.repository).to receive(:commits_by).once.and_call_original + + subject.first.title + subject.last.title + end + + it 'maintains ordering' do + subject.each_with_index do |commit, i| + expect(commit.id).to eq(oids[i]) + end + end + end + + context 'when not found' do + it 'returns nil as commit' do + commit = described_class.lazy(project, 'deadbeef').__sync + + expect(commit).to be_nil + end + end + end + describe '#author' do it 'looks up the author in a case-insensitive way' do user = create(:user, email: commit.author_email.upcase) diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 799d99c0369..8a3531c1898 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -239,6 +239,54 @@ describe Repository do end end + describe '#commits_by' do + set(:project) { create(:project, :repository) } + + shared_examples 'batch commits fetching' do + let(:oids) { TestEnv::BRANCH_SHA.values } + + subject { project.repository.commits_by(oids: oids) } + + it 'finds each commit' do + expect(subject).not_to include(nil) + expect(subject.size).to eq(oids.size) + end + + it 'returns only Commit instances' do + expect(subject).to all( be_a(Commit) ) + end + + context 'when some commits are not found ' do + let(:oids) do + ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10) + end + + it 'returns only found commits' do + expect(subject).not_to include(nil) + expect(subject.size).to eq(10) + end + end + + context 'when no oids are passed' do + let(:oids) { [] } + + it 'does not call #batch_by_oid' do + expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid) + + subject + end + end + end + + context 'when Gitaly list_commits_by_oid is enabled' do + it_behaves_like 'batch commits fetching' + end + + context 'when Gitaly list_commits_by_oid is enabled', :disable_gitaly do + it_behaves_like 'batch commits fetching' + end + end + describe '#find_commits_by_message' do shared_examples 'finding commits by message' do it 'returns commits with messages containing a given string' do diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb index 88d347322a6..c38795ad1a1 100644 --- a/spec/serializers/pipeline_serializer_spec.rb +++ b/spec/serializers/pipeline_serializer_spec.rb @@ -1,6 +1,7 @@ require 'spec_helper' describe PipelineSerializer do + set(:project) { create(:project, :repository) } set(:user) { create(:user) } let(:serializer) do @@ -16,7 +17,7 @@ describe PipelineSerializer do end context 'when a single object is being serialized' do - let(:resource) { create(:ci_empty_pipeline) } + let(:resource) { create(:ci_empty_pipeline, project: project) } it 'serializers the pipeline object' do expect(subject[:id]).to eq resource.id @@ -24,7 +25,7 @@ describe PipelineSerializer do end context 'when multiple objects are being serialized' do - let(:resource) { create_list(:ci_pipeline, 2) } + let(:resource) { create_list(:ci_pipeline, 2, project: project) } it 'serializers the array of pipelines' do expect(subject).not_to be_empty @@ -100,7 +101,6 @@ describe PipelineSerializer do context 'number of queries' do let(:resource) { Ci::Pipeline.all } - let(:project) { create(:project) } before do # Since RequestStore.active? is true we have to allow the -- cgit v1.2.1 From 8b13bdbe4d5805727c2c165f8cf0c7593c4af92d Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Tue, 19 Dec 2017 13:52:57 +0200 Subject: [CE->EE] Fix spec/lib/gitlab/git/gitlab_projects_spec.rb --- spec/lib/gitlab/git/gitlab_projects_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/git/gitlab_projects_spec.rb b/spec/lib/gitlab/git/gitlab_projects_spec.rb index 18906955df6..24da9589458 100644 --- a/spec/lib/gitlab/git/gitlab_projects_spec.rb +++ b/spec/lib/gitlab/git/gitlab_projects_spec.rb @@ -41,7 +41,8 @@ describe Gitlab::Git::GitlabProjects do end it "fails if the source path doesn't exist" do - expect(logger).to receive(:error).with("mv-project failed: source path <#{tmp_repos_path}/bad-src.git> does not exist.") + expected_source_path = File.join(tmp_repos_path, 'bad-src.git') + expect(logger).to receive(:error).with("mv-project failed: source path <#{expected_source_path}> does not exist.") result = build_gitlab_projects(tmp_repos_path, 'bad-src.git').mv_project('repo.git') expect(result).to be_falsy @@ -50,7 +51,8 @@ describe Gitlab::Git::GitlabProjects do it 'fails if the destination path already exists' do FileUtils.mkdir_p(File.join(tmp_repos_path, 'already-exists.git')) - message = "mv-project failed: destination path <#{tmp_repos_path}/already-exists.git> already exists." + expected_distination_path = File.join(tmp_repos_path, 'already-exists.git') + message = "mv-project failed: destination path <#{expected_distination_path}> already exists." expect(logger).to receive(:error).with(message) expect(gl_projects.mv_project('already-exists.git')).to be_falsy -- cgit v1.2.1 From ac862490392b029ac4937188e02bdf09f4505869 Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Tue, 19 Dec 2017 10:57:12 +0100 Subject: Don't link LFS-objects multiple times. If Unlinking a fork would fail somewhere after this, the LFS objects might still be linked. Which would cause issues when trying to destroy a project. --- spec/services/projects/unlink_fork_service_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/services/projects/unlink_fork_service_spec.rb b/spec/services/projects/unlink_fork_service_spec.rb index 2bba71fef4f..3ec6139bfa6 100644 --- a/spec/services/projects/unlink_fork_service_spec.rb +++ b/spec/services/projects/unlink_fork_service_spec.rb @@ -62,6 +62,26 @@ describe Projects::UnlinkForkService do expect(source.forks_count).to be_zero end + context 'when the source has LFS objects' do + let(:lfs_object) { create(:lfs_object) } + + before do + lfs_object.projects << project + end + + it 'links the fork to the lfs object before unlinking' do + subject.execute + + expect(lfs_object.projects).to include(forked_project) + end + + it 'does not fail if the lfs objects were already linked' do + lfs_object.projects << forked_project + + expect { subject.execute }.not_to raise_error + end + end + context 'when the original project was deleted' do it 'does not fail when the original project is deleted' do source = forked_project.forked_from_project -- cgit v1.2.1 From 23a38eac61f44c0ee3baed68ddcf23f28c03b20d Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 19 Dec 2017 16:18:48 +0000 Subject: Fix shortcut links on help page --- spec/features/help_pages_spec.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'spec') diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index ab896a310be..0d04ed612c2 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -32,6 +32,24 @@ describe 'Help Pages' do it_behaves_like 'help page', prefix: '/gitlab' end + + context 'quick link shortcuts', :js do + before do + visit help_path + end + + it 'focuses search bar' do + find('.js-trigger-search-bar').click + + expect(page).to have_selector('#search:focus') + end + + it 'opens shortcuts help dialog' do + find('.js-trigger-shortcut').click + + expect(page).to have_selector('#modal-shortcuts') + end + end end context 'in a production environment with version check enabled', :js do -- cgit v1.2.1 From 9410fbef9fa3979673b3769c5dc40686ea125240 Mon Sep 17 00:00:00 2001 From: Mario de la Ossa Date: Tue, 19 Dec 2017 17:02:56 +0000 Subject: Fix tags in the Activity tab not being clickable --- spec/views/events/event/_push.html.haml_spec.rb | 55 +++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 spec/views/events/event/_push.html.haml_spec.rb (limited to 'spec') diff --git a/spec/views/events/event/_push.html.haml_spec.rb b/spec/views/events/event/_push.html.haml_spec.rb new file mode 100644 index 00000000000..f5634de4916 --- /dev/null +++ b/spec/views/events/event/_push.html.haml_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe 'events/event/_push.html.haml' do + let(:event) { build_stubbed(:push_event) } + + context 'with a branch' do + let(:payload) { build_stubbed(:push_event_payload, event: event) } + + before do + allow(event).to receive(:push_event_payload).and_return(payload) + end + + it 'links to the branch' do + allow(event.project.repository).to receive(:branch_exists?).with(event.ref_name).and_return(true) + link = project_commits_path(event.project, event.ref_name) + + render partial: 'events/event/push', locals: { event: event } + + expect(rendered).to have_link(event.ref_name, href: link) + end + + context 'that has been deleted' do + it 'does not link to the branch' do + render partial: 'events/event/push', locals: { event: event } + + expect(rendered).not_to have_link(event.ref_name) + end + end + end + + context 'with a tag' do + let(:payload) { build_stubbed(:push_event_payload, event: event, ref_type: :tag, ref: 'v0.1.0') } + + before do + allow(event).to receive(:push_event_payload).and_return(payload) + end + + it 'links to the tag' do + allow(event.project.repository).to receive(:tag_exists?).with(event.ref_name).and_return(true) + link = project_commits_path(event.project, event.ref_name) + + render partial: 'events/event/push', locals: { event: event } + + expect(rendered).to have_link(event.ref_name, href: link) + end + + context 'that has been deleted' do + it 'does not link to the tag' do + render partial: 'events/event/push', locals: { event: event } + + expect(rendered).not_to have_link(event.ref_name) + end + end + end +end -- cgit v1.2.1 From 271ebe661103b4b523ae9e50f755df9a7aeedb1d Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 19 Dec 2017 17:48:29 +0000 Subject: Show inline edit button for issues --- spec/features/issues/issue_detail_spec.rb | 2 +- spec/features/projects/issuable_templates_spec.rb | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'spec') diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb index 4224a8fe5d4..babb0285590 100644 --- a/spec/features/issues/issue_detail_spec.rb +++ b/spec/features/issues/issue_detail_spec.rb @@ -24,7 +24,7 @@ feature 'Issue Detail', :js do visit project_issue_path(project, issue) wait_for_requests - click_link 'Edit' + page.find('.js-issuable-edit').click fill_in 'issuable-title', with: 'issue title' click_button 'Save' wait_for_requests diff --git a/spec/features/projects/issuable_templates_spec.rb b/spec/features/projects/issuable_templates_spec.rb index 0257cd157c9..4319fc2746c 100644 --- a/spec/features/projects/issuable_templates_spec.rb +++ b/spec/features/projects/issuable_templates_spec.rb @@ -32,9 +32,7 @@ feature 'issuable templates', :js do message: 'added issue template', branch_name: 'master') visit project_issue_path project, issue - page.within('.js-issuable-actions') do - click_on 'Edit' - end + page.find('.js-issuable-edit').click fill_in :'issuable-title', with: 'test issue title' end @@ -77,9 +75,7 @@ feature 'issuable templates', :js do message: 'added issue template', branch_name: 'master') visit project_issue_path project, issue - page.within('.js-issuable-actions') do - click_on 'Edit' - end + page.find('.js-issuable-edit').click fill_in :'issuable-title', with: 'test issue title' fill_in :'issue-description', with: prior_description end -- cgit v1.2.1 From 0a0a62c93636627e2c1c34a41af33e178efd7647 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Tue, 19 Dec 2017 17:50:38 +0000 Subject: Remove related links in MR widget when empty state --- .../vue_mr_widget/mr_widget_options_spec.js | 28 ++++++++++++++++++++++ .../vue_mr_widget/stores/mr_widget_store_spec.js | 13 ++++++++++ 2 files changed, 41 insertions(+) (limited to 'spec') diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js index 9e6d0aa472c..74b343c573e 100644 --- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js +++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import mrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options'; import eventHub from '~/vue_merge_request_widget/event_hub'; import notify from '~/lib/utils/notify'; +import { stateKey } from '~/vue_merge_request_widget/stores/state_maps'; import mockData from './mock_data'; import mountComponent from '../helpers/vue_mount_component_helper'; @@ -344,4 +345,31 @@ describe('mrWidgetOptions', () => { expect(comps['mr-widget-merge-when-pipeline-succeeds']).toBeDefined(); }); }); + + describe('rendering relatedLinks', () => { + beforeEach((done) => { + vm.mr.relatedLinks = { + assignToMe: null, + closing: ` + Date: Tue, 19 Dec 2017 18:36:53 +0000 Subject: Prevent some specs from mangling the gitlab-shell checkout --- ...wner_sees_link_to_create_license_file_in_empty_project_spec.rb | 8 +++----- spec/features/tags/master_views_tags_spec.rb | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'spec') diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 6c616bf0456..8ac9821b879 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -2,15 +2,15 @@ require 'spec_helper' feature 'project owner sees a link to create a license file in empty project', :js do let(:project_master) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:project_empty_repo) } + background do - project.team << [project_master, :master] + project.add_master(project_master) sign_in(project_master) end scenario 'project master creates a license file from a template' do visit project_path(project) - click_link 'Create empty bare repository' click_on 'LICENSE' expect(page).to have_content('New file') @@ -26,8 +26,6 @@ feature 'project owner sees a link to create a license file in empty project', : expect(file_content).to have_content("Copyright (c) #{Time.now.year} #{project.namespace.human_name}") fill_in :commit_message, with: 'Add a LICENSE file', visible: true - # Remove pre-receive hook so we can push without auth - FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive')) click_button 'Commit changes' expect(current_path).to eq( diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb index 9edc7ced163..4662367d843 100644 --- a/spec/features/tags/master_views_tags_spec.rb +++ b/spec/features/tags/master_views_tags_spec.rb @@ -4,18 +4,17 @@ feature 'Master views tags' do let(:user) { create(:user) } before do - project.team << [user, :master] + project.add_master(user) sign_in(user) end context 'when project has no tags' do let(:project) { create(:project_empty_repo) } + before do visit project_path(project) click_on 'README' fill_in :commit_message, with: 'Add a README file', visible: true - # Remove pre-receive hook so we can push without auth - FileUtils.rm_f(File.join(project.repository.path, 'hooks', 'pre-receive')) click_button 'Commit changes' visit project_tags_path(project) end -- cgit v1.2.1 From 32ff813d3dccef6378361dff599eca44b05f46d4 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Mon, 18 Sep 2017 23:18:51 -0400 Subject: Add BlocksJsonSerialization model concern and include it in User --- spec/models/concerns/blocks_json_serialization_spec.rb | 17 +++++++++++++++++ spec/models/user_spec.rb | 1 + 2 files changed, 18 insertions(+) create mode 100644 spec/models/concerns/blocks_json_serialization_spec.rb (limited to 'spec') diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb new file mode 100644 index 00000000000..84f8ccc238e --- /dev/null +++ b/spec/models/concerns/blocks_json_serialization_spec.rb @@ -0,0 +1,17 @@ +require 'rails_helper' + +describe BlocksJsonSerialization do + DummyModel = Class.new do + include BlocksJsonSerialization + end + + it 'blocks as_json' do + expect { DummyModel.new.to_json } + .to raise_error(SecurityError, "JSON serialization has been disabled on DummyModel") + end + + it 'blocks to_json' do + expect { DummyModel.new.to_json } + .to raise_error(SecurityError, "JSON serialization has been disabled on DummyModel") + end +end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 4687d9dfa00..e58e7588df0 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -12,6 +12,7 @@ describe User do it { is_expected.to include_module(Referable) } it { is_expected.to include_module(Sortable) } it { is_expected.to include_module(TokenAuthenticatable) } + it { is_expected.to include_module(BlocksJsonSerialization) } end describe 'delegations' do -- cgit v1.2.1 From 8d0ad36bcfc0ef95ee9a116604ba1516367dbb27 Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Fri, 1 Dec 2017 11:33:02 -0600 Subject: Add a JsonSerializationError class instead of raising SecurityError --- spec/models/concerns/blocks_json_serialization_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb index 84f8ccc238e..571ed7d5b26 100644 --- a/spec/models/concerns/blocks_json_serialization_spec.rb +++ b/spec/models/concerns/blocks_json_serialization_spec.rb @@ -7,11 +7,11 @@ describe BlocksJsonSerialization do it 'blocks as_json' do expect { DummyModel.new.to_json } - .to raise_error(SecurityError, "JSON serialization has been disabled on DummyModel") + .to raise_error(described_class::JsonSerializationError, /DummyModel/) end it 'blocks to_json' do expect { DummyModel.new.to_json } - .to raise_error(SecurityError, "JSON serialization has been disabled on DummyModel") + .to raise_error(described_class::JsonSerializationError, /DummyModel/) end end -- cgit v1.2.1 From 3e4b45fc216875ff25647675d92448a53a740d9b Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Thu, 14 Dec 2017 13:32:55 -0600 Subject: Only include the user's ID in the time_spent command's update hash Previously, this would include the entire User record in the update hash, which was rendered in the response using `to_json`, erroneously exposing every attribute of that record, including their (now removed) private token. Now we only include the user ID, and perform the lookup on-demand. --- spec/features/milestone_spec.rb | 4 ++-- spec/models/concerns/issuable_spec.rb | 4 ++-- spec/models/concerns/milestoneish_spec.rb | 4 ++-- spec/services/quick_actions/interpret_service_spec.rb | 8 ++++---- spec/services/system_note_service_spec.rb | 4 ++-- spec/support/api/time_tracking_shared_examples.rb | 6 +++--- spec/support/api/v3/time_tracking_shared_examples.rb | 6 +++--- 7 files changed, 18 insertions(+), 18 deletions(-) (limited to 'spec') diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index 27efc32c95b..9f24193a2ac 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -82,9 +82,9 @@ feature 'Milestone' do milestone = create(:milestone, project: project, title: 8.7) issue1 = create(:issue, project: project, milestone: milestone) issue2 = create(:issue, project: project, milestone: milestone) - issue1.spend_time(duration: 3600, user: user) + issue1.spend_time(duration: 3600, user_id: user.id) issue1.save! - issue2.spend_time(duration: 7200, user: user) + issue2.spend_time(duration: 7200, user_id: user.id) issue2.save! visit project_milestone_path(project, milestone) diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 9df26f06a11..4b217df2e8f 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -291,7 +291,7 @@ describe Issuable do context 'total_time_spent is updated' do before do - issue.spend_time(duration: 2, user: user, spent_at: Time.now) + issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.now) issue.save expect(Gitlab::HookData::IssuableBuilder) .to receive(:new).with(issue).and_return(builder) @@ -485,7 +485,7 @@ describe Issuable do let(:issue) { create(:issue) } def spend_time(seconds) - issue.spend_time(duration: seconds, user: user) + issue.spend_time(duration: seconds, user_id: user.id) issue.save! end diff --git a/spec/models/concerns/milestoneish_spec.rb b/spec/models/concerns/milestoneish_spec.rb index 9048da0c73d..673c609f534 100644 --- a/spec/models/concerns/milestoneish_spec.rb +++ b/spec/models/concerns/milestoneish_spec.rb @@ -189,9 +189,9 @@ describe Milestone, 'Milestoneish' do describe '#total_issue_time_spent' do it 'calculates total issue time spent' do - closed_issue_1.spend_time(duration: 300, user: author) + closed_issue_1.spend_time(duration: 300, user_id: author.id) closed_issue_1.save! - closed_issue_2.spend_time(duration: 600, user: assignee) + closed_issue_2.spend_time(duration: 600, user_id: assignee.id) closed_issue_2.save! expect(milestone.total_issue_time_spent).to eq(900) diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index c35177f6ebc..eb46480fa54 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -209,7 +209,7 @@ describe QuickActions::InterpretService do expect(updates).to eq(spend_time: { duration: 3600, - user: developer, + user_id: developer.id, spent_at: DateTime.now.to_date }) end @@ -221,7 +221,7 @@ describe QuickActions::InterpretService do expect(updates).to eq(spend_time: { duration: -1800, - user: developer, + user_id: developer.id, spent_at: DateTime.now.to_date }) end @@ -233,7 +233,7 @@ describe QuickActions::InterpretService do expect(updates).to eq(spend_time: { duration: 1800, - user: developer, + user_id: developer.id, spent_at: Date.parse(date) }) end @@ -267,7 +267,7 @@ describe QuickActions::InterpretService do it 'populates spend_time: :reset if content contains /remove_time_spent' do _, updates = service.execute(content, issuable) - expect(updates).to eq(spend_time: { duration: :reset, user: developer }) + expect(updates).to eq(spend_time: { duration: :reset, user_id: developer.id }) end end diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb index 47412110b4b..9025589ae0b 100644 --- a/spec/services/system_note_service_spec.rb +++ b/spec/services/system_note_service_spec.rb @@ -927,7 +927,7 @@ describe SystemNoteService do # We need a custom noteable in order to the shared examples to be green. let(:noteable) do mr = create(:merge_request, source_project: project) - mr.spend_time(duration: 360000, user: author) + mr.spend_time(duration: 360000, user_id: author.id) mr.save! mr end @@ -965,7 +965,7 @@ describe SystemNoteService do end def spend_time!(seconds) - noteable.spend_time(duration: seconds, user: author) + noteable.spend_time(duration: seconds, user_id: author.id) noteable.save! end end diff --git a/spec/support/api/time_tracking_shared_examples.rb b/spec/support/api/time_tracking_shared_examples.rb index af1083f4bfd..dd3089d22e5 100644 --- a/spec/support/api/time_tracking_shared_examples.rb +++ b/spec/support/api/time_tracking_shared_examples.rb @@ -79,7 +79,7 @@ shared_examples 'time tracking endpoints' do |issuable_name| context 'when subtracting time' do it 'subtracts time of the total spent time' do - issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id }) post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), duration: '-1h' @@ -91,7 +91,7 @@ shared_examples 'time tracking endpoints' do |issuable_name| context 'when time to subtract is greater than the total spent time' do it 'does not modify the total time spent' do - issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id }) post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), duration: '-1w' @@ -119,7 +119,7 @@ shared_examples 'time tracking endpoints' do |issuable_name| describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do it "returns the time stats for #{issuable_name}" do - issuable.update_attributes!(spend_time: { duration: 1800, user: user }, + issuable.update_attributes!(spend_time: { duration: 1800, user_id: user.id }, time_estimate: 3600) get api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/time_stats", user) diff --git a/spec/support/api/v3/time_tracking_shared_examples.rb b/spec/support/api/v3/time_tracking_shared_examples.rb index afe0f4cecda..f27a2d06c83 100644 --- a/spec/support/api/v3/time_tracking_shared_examples.rb +++ b/spec/support/api/v3/time_tracking_shared_examples.rb @@ -75,7 +75,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name| context 'when subtracting time' do it 'subtracts time of the total spent time' do - issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id }) post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user), duration: '-1h' @@ -87,7 +87,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name| context 'when time to subtract is greater than the total spent time' do it 'does not modify the total time spent' do - issuable.update_attributes!(spend_time: { duration: 7200, user: user }) + issuable.update_attributes!(spend_time: { duration: 7200, user_id: user.id }) post v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/add_spent_time", user), duration: '-1w' @@ -115,7 +115,7 @@ shared_examples 'V3 time tracking endpoints' do |issuable_name| describe "GET /projects/:id/#{issuable_collection_name}/:#{issuable_name}_id/time_stats" do it "returns the time stats for #{issuable_name}" do - issuable.update_attributes!(spend_time: { duration: 1800, user: user }, + issuable.update_attributes!(spend_time: { duration: 1800, user_id: user.id }, time_estimate: 3600) get v3_api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.id}/time_stats", user) -- cgit v1.2.1 From 099e274266f7c63ec43b02d79577a74265feb67c Mon Sep 17 00:00:00 2001 From: Robert Speicher Date: Tue, 19 Dec 2017 15:44:54 -0600 Subject: Call the correct method in the BlocksJsonSerialization spec --- spec/models/concerns/blocks_json_serialization_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb index 571ed7d5b26..5906b588d0e 100644 --- a/spec/models/concerns/blocks_json_serialization_spec.rb +++ b/spec/models/concerns/blocks_json_serialization_spec.rb @@ -6,7 +6,7 @@ describe BlocksJsonSerialization do end it 'blocks as_json' do - expect { DummyModel.new.to_json } + expect { DummyModel.new.as_json } .to raise_error(described_class::JsonSerializationError, /DummyModel/) end -- cgit v1.2.1 From 055543b915c13df57e13629cd49ca9d63b6e3e76 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Tue, 19 Dec 2017 22:00:17 +0000 Subject: Add optional `search` param for Merge Requests API --- spec/requests/api/merge_requests_spec.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'spec') diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 91616da6d9a..60dbd74d59d 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -150,6 +150,26 @@ describe API::MergeRequests do expect(json_response.length).to eq(1) expect(json_response.first['id']).to eq(merge_request3.id) end + + context 'search params' do + before do + merge_request.update(title: 'Search title', description: 'Search description') + end + + it 'returns merge requests matching given search string for title' do + get api("/merge_requests", user), search: merge_request.title + + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request.id) + end + + it 'returns merge requests for project matching given search string for description' do + get api("/merge_requests", user), project_id: project.id, search: merge_request.description + + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(merge_request.id) + end + end end end -- cgit v1.2.1 From 1ed8cf1c50ce2f7e68c5d284c0c81393d2af6788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 20 Dec 2017 18:47:45 +0100 Subject: Fix a failure because we stub DiffHelper#diff_file_blob_raw_path instead of #diff_file_blob_raw_url MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- spec/features/merge_requests/image_diff_notes_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'spec') diff --git a/spec/features/merge_requests/image_diff_notes_spec.rb b/spec/features/merge_requests/image_diff_notes_spec.rb index ddc73437917..42fc42422eb 100644 --- a/spec/features/merge_requests/image_diff_notes_spec.rb +++ b/spec/features/merge_requests/image_diff_notes_spec.rb @@ -12,7 +12,7 @@ feature 'image diff notes', :js do # Stub helper to return any blob file as image from public app folder. # This is necessary to run this specs since we don't display repo images in capybara. - allow_any_instance_of(DiffHelper).to receive(:diff_file_blob_raw_path).and_return('/apple-touch-icon.png') + allow_any_instance_of(DiffHelper).to receive(:diff_file_blob_raw_url).and_return('/apple-touch-icon.png') end context 'create commit diff notes' do @@ -192,7 +192,7 @@ feature 'image diff notes', :js do it 'resizes image in onion skin view mode' do find('.view-modes-menu .onion-skin').click - expect(find('.onion-skin-frame')['style']).to match('width: 228px; height: 240px;') + expect(find('.onion-skin-frame')['style']).to match('width: 243px; height: 240px;') end it 'resets onion skin view mode opacity when toggling between view modes' do -- cgit v1.2.1 From 338f1eaf354a31663afbda3d91776f7f506b90f1 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Wed, 20 Dec 2017 19:13:11 +0100 Subject: Migrate to Project#empty_repo? --- .../lib/gitlab/github_import/importer/repository_importer_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec') diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb index 168e5d07504..46a57e08963 100644 --- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb @@ -70,7 +70,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do describe '#execute' do it 'imports the repository and wiki' do - expect(repository) + expect(project) .to receive(:empty_repo?) .and_return(true) @@ -93,7 +93,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do end it 'does not import the repository if it already exists' do - expect(repository) + expect(project) .to receive(:empty_repo?) .and_return(false) @@ -115,7 +115,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do end it 'does not import the wiki if it is disabled' do - expect(repository) + expect(project) .to receive(:empty_repo?) .and_return(true) @@ -137,7 +137,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do end it 'does not import the wiki if the repository could not be imported' do - expect(repository) + expect(project) .to receive(:empty_repo?) .and_return(true) -- cgit v1.2.1 From 28fba5ed99c6f8b4e7e534f9c2046d1c5ab38607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kim=20Carlb=C3=A4cker?= Date: Wed, 20 Dec 2017 18:29:52 +0000 Subject: Revert "Merge branch 'repo-write-ref-client-prep' into 'master'" This reverts merge request !15712 --- spec/models/project_spec.rb | 5 ++--- spec/models/repository_spec.rb | 17 ----------------- 2 files changed, 2 insertions(+), 20 deletions(-) (limited to 'spec') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index f805f2dcddb..cbeac2f05d3 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1863,11 +1863,10 @@ describe Project do project.change_head(project.default_branch) end - it 'creates the new reference' do - expect(project.repository.raw_repository).to receive(:write_ref).with('HEAD', + it 'creates the new reference with rugged' do + expect(project.repository.rugged.references).to receive(:create).with('HEAD', "refs/heads/#{project.default_branch}", force: true) - project.change_head(project.default_branch) end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 1d7069feebd..9a68ae086ea 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1979,23 +1979,6 @@ describe Repository do File.delete(path) end - - it "attempting to call keep_around when exists a lock does not fail" do - ref = repository.send(:keep_around_ref_name, sample_commit.id) - path = File.join(repository.path, ref) - lock_path = "#{path}.lock" - - FileUtils.mkdir_p(File.dirname(path)) - File.open(lock_path, 'w') { |f| f.write('') } - - begin - expect { repository.keep_around(sample_commit.id) }.not_to raise_error(Gitlab::Git::Repository::GitError) - - expect(File.exist?(lock_path)).to be_falsey - ensure - File.delete(path) - end - end end describe '#update_ref' do -- cgit v1.2.1 From 48dfc670d3300d5593ad161be9954c090ca896ee Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 20 Dec 2017 16:36:43 -0600 Subject: Stub old image diff url --- spec/features/merge_requests/image_diff_notes_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'spec') diff --git a/spec/features/merge_requests/image_diff_notes_spec.rb b/spec/features/merge_requests/image_diff_notes_spec.rb index 42fc42422eb..b53570835cb 100644 --- a/spec/features/merge_requests/image_diff_notes_spec.rb +++ b/spec/features/merge_requests/image_diff_notes_spec.rb @@ -13,6 +13,7 @@ feature 'image diff notes', :js do # Stub helper to return any blob file as image from public app folder. # This is necessary to run this specs since we don't display repo images in capybara. allow_any_instance_of(DiffHelper).to receive(:diff_file_blob_raw_url).and_return('/apple-touch-icon.png') + allow_any_instance_of(DiffHelper).to receive(:diff_file_old_blob_raw_url).and_return('/favicon.ico') end context 'create commit diff notes' do @@ -192,7 +193,7 @@ feature 'image diff notes', :js do it 'resizes image in onion skin view mode' do find('.view-modes-menu .onion-skin').click - expect(find('.onion-skin-frame')['style']).to match('width: 243px; height: 240px;') + expect(find('.onion-skin-frame')['style']).to match('width: 228px; height: 240px;') end it 'resets onion skin view mode opacity when toggling between view modes' do -- cgit v1.2.1