diff options
author | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-11-30 14:21:33 +0300 |
---|---|---|
committer | Grzegorz Bizon <grzesiek.bizon@gmail.com> | 2016-11-30 14:21:33 +0300 |
commit | 00ca7adca2de8ff05cca3df9eb2df8a67f638cfe (patch) | |
tree | 86764da0f493a7169b2fea59e5618b669cd64d56 /spec | |
parent | adb3f3d4e494e8f8d41c1b9e676e395a49cd96b2 (diff) | |
parent | 7e5fa10b665835e3160eee4d333a17fbaef9c113 (diff) |
Merge branch 'master' into fix/rename-mwbs-to-merge-when-pipeline-succeeds
* master: (110 commits)
Rewrite an HTTP link to use HTTPS
Edit /spec/features/profiles/preferences_spec.rb to match changes in 084d90ac
Add blue back to sub nav active
Remove JSX/React eslint plugins.
Fix a transient spec failure
Adds hoverstates for collapsed Issue/Merge Request sidebar
Moved groups above projects
Add StackProf to the Gemfile, along with a utility to get a profile for a spec
Update Sidekiq-cron to fix compatibility issues with Sidekiq 4.2.1
Add a CHANGELOG entry
Alert user when logged in user email is not the same as the invitation
Expose timestamp in build entity used by serializer
Rename `MergeRequest#pipeline` to `head_pipeline`
Remove unnecessary database indexes
CE-specific changes gitlab-org/gitlab-ee#1137
Fixing typo & Clarifying Key name
fix started_at check
fix blob controller spec failure - updated not to use file-path-
fix blob controller spec failure
Merge branch 'jej-use-issuable-finder-instead-of-access-check' into 'security'
...
Conflicts:
app/controllers/projects/merge_requests_controller.rb
lib/api/merge_requests.rb
spec/requests/api/merge_requests_spec.rb
Diffstat (limited to 'spec')
70 files changed, 1887 insertions, 1241 deletions
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index d9a86346c81..0d1545040f1 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -4,7 +4,7 @@ describe AutocompleteController do let!(:project) { create(:project) } let!(:user) { create(:user) } - context 'users and members' do + context 'GET users' do let!(:user2) { create(:user) } let!(:non_member) { create(:user) } @@ -180,7 +180,7 @@ describe AutocompleteController do end end - context 'projects' do + context 'GET projects' do let(:authorized_project) { create(:project) } let(:authorized_search_project) { create(:project, name: 'rugged') } diff --git a/spec/controllers/help_controller_spec.rb b/spec/controllers/help_controller_spec.rb index 6fc6ea95e13..cffed987f6b 100644 --- a/spec/controllers/help_controller_spec.rb +++ b/spec/controllers/help_controller_spec.rb @@ -16,14 +16,6 @@ describe HelpController do end end - context 'when url prefixed with help/' do - it 'will be an absolute path' do - stub_readme("[API](help/api/README.md)") - get :index - expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' - end - end - context 'when url prefixed with help' do it 'will be an absolute path' do stub_readme("[API](helpful_hints/README.md)") @@ -32,11 +24,11 @@ describe HelpController do end end - context 'when url prefixed with /help/' do + context 'when url is an external link' do it 'will not be changed' do - stub_readme("[API](/help/api/README.md)") + stub_readme("[external](https://some.external.link)") get :index - expect(assigns[:help_index]).to eq '[API](/help/api/README.md)' + expect(assigns[:help_index]).to eq '[external](https://some.external.link)' end end end diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 52d13fb6f9e..3efef757ae2 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -36,4 +36,53 @@ describe Projects::BlobController do end end end + + describe 'PUT update' do + let(:default_params) do + { + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: 'master/CHANGELOG', + target_branch: 'master', + content: 'Added changes', + commit_message: 'Update CHANGELOG' + } + end + + def blob_after_edit_path + namespace_project_blob_path(project.namespace, project, 'master/CHANGELOG') + end + + it 'redirects to blob' do + put :update, default_params + + expect(response).to redirect_to(blob_after_edit_path) + end + + context '?from_merge_request_iid' do + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:mr_params) { default_params.merge(from_merge_request_iid: merge_request.iid) } + + it 'redirects to MR diff' do + put :update, mr_params + + after_edit_path = diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + file_anchor = "##{Digest::SHA1.hexdigest('CHANGELOG')}" + expect(response).to redirect_to(after_edit_path + file_anchor) + end + + context "when user doesn't have access" do + before do + other_project = create(:empty_project) + merge_request.update!(source_project: other_project, target_project: other_project) + end + + it "it redirect to blob" do + put :update, mr_params + + expect(response).to redirect_to(blob_after_edit_path) + end + end + end + end end diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb index f7cf006efd6..b88586b8678 100644 --- a/spec/controllers/projects/branches_controller_spec.rb +++ b/spec/controllers/projects/branches_controller_spec.rb @@ -94,6 +94,24 @@ describe Projects::BranchesController do branch_name: branch, issue_iid: issue.iid end + + context 'without issue feature access' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) + project.team.truncate + end + + it "doesn't post a system note" do + expect(SystemNoteService).not_to receive(:new_issue_branch) + + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch_name: branch, + issue_iid: issue.iid + end + end end end diff --git a/spec/controllers/projects/todo_controller_spec.rb b/spec/controllers/projects/todo_controller_spec.rb index 936320a3709..193a3f6b5a3 100644 --- a/spec/controllers/projects/todo_controller_spec.rb +++ b/spec/controllers/projects/todo_controller_spec.rb @@ -4,7 +4,7 @@ describe Projects::TodosController do include ApiHelpers let(:user) { create(:user) } - let(:project) { create(:project) } + let(:project) { create(:empty_project) } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, source_project: project) } @@ -42,7 +42,7 @@ describe Projects::TodosController do end end - context 'when not authorized' do + context 'when not authorized for project' do it 'does not create todo for issue that user has no access to' do sign_in(user) expect do @@ -60,6 +60,19 @@ describe Projects::TodosController do expect(response).to have_http_status(302) end end + + context 'when not authorized for issue' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE) + sign_in(user) + end + + it "doesn't create todo" do + expect{ go }.not_to change { user.todos.count } + expect(response).to have_http_status(404) + end + end end end diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb index 2d762fdaa04..d76fe9f580f 100644 --- a/spec/controllers/snippets_controller_spec.rb +++ b/spec/controllers/snippets_controller_spec.rb @@ -3,6 +3,28 @@ require 'spec_helper' describe SnippetsController do let(:user) { create(:user) } + describe 'GET #new' do + context 'when signed in' do + before do + sign_in(user) + end + + it 'responds with status 200' do + get :new + + expect(response).to have_http_status(200) + end + end + + context 'when not signed in' do + it 'redirects to the sign in page' do + get :new + + expect(response).to redirect_to(new_user_session_path) + end + end + end + describe 'GET #show' do context 'when the personal snippet is private' do let(:personal_snippet) { create(:personal_snippet, :private, author: user) } diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb index ac2a1ba5dff..1735791f644 100644 --- a/spec/factories/ci/pipelines.rb +++ b/spec/factories/ci/pipelines.rb @@ -7,26 +7,30 @@ FactoryGirl.define do project factory: :empty_project factory :ci_pipeline_without_jobs do - after(:build) do |commit| - allow(commit).to receive(:ci_yaml_file) { YAML.dump({}) } + after(:build) do |pipeline| + allow(pipeline).to receive(:ci_yaml_file) { YAML.dump({}) } end end factory :ci_pipeline_with_one_job do - after(:build) do |commit| - allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" } }) } - end - end - - factory :ci_pipeline_with_two_job do - after(:build) do |commit| - allow(commit).to receive(:ci_yaml_file) { YAML.dump({ rspec: { script: "ls" }, spinach: { script: "ls" } }) } + after(:build) do |pipeline| + allow(pipeline).to receive(:ci_yaml_file) do + YAML.dump({ rspec: { script: "ls" } }) + end end end factory :ci_pipeline do - after(:build) do |commit| - allow(commit).to receive(:ci_yaml_file) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) } + transient { config nil } + + after(:build) do |pipeline, evaluator| + allow(pipeline).to receive(:ci_yaml_file) do + if evaluator.config + YAML.dump(evaluator.config) + else + File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + end + end end end end diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index e2101b333e2..73d03837144 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -10,4 +10,28 @@ describe 'Help Pages', feature: true do expect(page).to have_content("ssh-keygen -t rsa -C \"#{@user.email}\"") end end + + describe 'Get the main help page' do + shared_examples_for 'help page' do + it 'prefixes links correctly' do + expect(page).to have_selector('div.documentation-index > ul a[href="/help/api/README.md"]') + end + end + + context 'without a trailing slash' do + before do + visit help_path + end + + it_behaves_like 'help page' + end + + context 'with a trailing slash' do + before do + visit help_path + '/' + end + + it_behaves_like 'help page' + end + end end diff --git a/spec/features/profiles/preferences_spec.rb b/spec/features/profiles/preferences_spec.rb index d14a1158b67..a6b841c0210 100644 --- a/spec/features/profiles/preferences_spec.rb +++ b/spec/features/profiles/preferences_spec.rb @@ -73,7 +73,7 @@ describe 'Profile > Preferences', feature: true do expect(page.current_path).to eq starred_dashboard_projects_path end - click_link 'Your Projects' + click_link 'Your projects' expect(page).not_to have_content("You don't have starred projects yet") expect(page.current_path).to eq dashboard_projects_path diff --git a/spec/features/projects/blobs/edit_spec.rb b/spec/features/projects/blobs/edit_spec.rb new file mode 100644 index 00000000000..a820d07ab3b --- /dev/null +++ b/spec/features/projects/blobs/edit_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +feature 'Editing file blob', feature: true, js: true do + include WaitForAjax + + given(:user) { create(:user) } + given(:role) { :developer } + given(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') } + given(:project) { merge_request.target_project } + + background do + login_as(user) + project.team << [user, role] + end + + def edit_and_commit + wait_for_ajax + first('.file-actions').click_link 'Edit' + execute_script('ace.edit("editor").setValue("class NextFeature\nend\n")') + click_button 'Commit Changes' + end + + context 'from MR diff' do + before do + visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) + edit_and_commit + end + + scenario 'returns me to the mr' do + expect(page).to have_content(merge_request.title) + end + end + + context 'from blob file path' do + before do + visit namespace_project_blob_path(project.namespace, project, '/feature/files/ruby/feature.rb') + edit_and_commit + end + + scenario 'updates content' do + expect(page).to have_content 'successfully committed' + expect(page).to have_content 'NextFeature' + end + end +end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index b6acc509342..1897c8119d2 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -5,19 +5,6 @@ describe "Internal Project Access", feature: true do let(:project) { create(:project, :internal) } - let(:owner) { project.owner } - let(:master) { create(:user) } - let(:developer) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - - before do - project.team << [master, :master] - project.team << [developer, :developer] - project.team << [reporter, :reporter] - project.team << [guest, :guest] - end - describe "Project should be internal" do describe '#internal?' do subject { project.internal? } @@ -28,213 +15,213 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path" do subject { namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/tree/master" do subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/commits/master" do subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/commit/:sha" do subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/compare" do subject { namespace_project_compare_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/project_members" do subject { namespace_project_project_members_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :visitor } - it { is_expected.to be_denied_for :external } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:visitor) } + it { is_expected.to be_denied_for(:external) } end describe "GET /:project_path/blob" do let(:commit) { project.repository.commit } subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/edit" do subject { edit_namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/deploy_keys" do subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/issues" do subject { namespace_project_issues_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } subject { edit_namespace_project_issue_path(project.namespace, project, issue) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/snippets" do subject { namespace_project_snippets_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/snippets/new" do subject { new_namespace_project_snippet_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/merge_requests" do subject { namespace_project_merge_requests_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/merge_requests/new" do subject { new_namespace_project_merge_request_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/branches" do @@ -245,15 +232,15 @@ describe "Internal Project Access", feature: true do allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/tags" do @@ -264,58 +251,58 @@ describe "Internal Project Access", feature: true do allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/hooks" do subject { namespace_project_hooks_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/pipelines" do subject { namespace_project_pipelines_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/builds" do @@ -324,29 +311,29 @@ describe "Internal Project Access", feature: true do context "when allowed for public and internal" do before { project.update(public_builds: true) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end context "when disallowed for public and internal" do before { project.update(public_builds: false) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end @@ -358,73 +345,73 @@ describe "Internal Project Access", feature: true do context "when allowed for public and internal" do before { project.update(public_builds: true) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end context "when disallowed for public and internal" do before { project.update(public_builds: false) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end describe "GET /:project_path/environments" do subject { namespace_project_environments_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } subject { namespace_project_environment_path(project.namespace, project, environment) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/new" do subject { new_namespace_project_environment_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/container_registry" do @@ -435,14 +422,14 @@ describe "Internal Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 79417c769a8..290ddb4c6dd 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -5,19 +5,6 @@ describe "Private Project Access", feature: true do let(:project) { create(:project, :private) } - let(:owner) { project.owner } - let(:master) { create(:user) } - let(:developer) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - - before do - project.team << [master, :master] - project.team << [developer, :developer] - project.team << [reporter, :reporter] - project.team << [guest, :guest] - end - describe "Project should be private" do describe '#private?' do subject { project.private? } @@ -28,185 +15,185 @@ describe "Private Project Access", feature: true do describe "GET /:project_path" do subject { namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/tree/master" do subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/commits/master" do subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/commit/:sha" do subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/compare" do subject { namespace_project_compare_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/project_members" do subject { namespace_project_project_members_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/blob" do let(:commit) { project.repository.commit } subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore'))} - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/edit" do subject { edit_namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/deploy_keys" do subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/issues" do subject { namespace_project_issues_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } subject { edit_namespace_project_issue_path(project.namespace, project, issue) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/snippets" do subject { namespace_project_snippets_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/merge_requests" do subject { namespace_project_merge_requests_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/branches" do @@ -217,15 +204,15 @@ describe "Private Project Access", feature: true do allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/tags" do @@ -236,72 +223,72 @@ describe "Private Project Access", feature: true do allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/hooks" do subject { namespace_project_hooks_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/pipelines" do subject { namespace_project_pipelines_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/builds" do subject { namespace_project_builds_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/builds/:id" do @@ -309,58 +296,58 @@ describe "Private Project Access", feature: true do let(:build) { create(:ci_build, pipeline: pipeline) } subject { namespace_project_build_path(project.namespace, project, build.id) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments" do subject { namespace_project_environments_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } subject { namespace_project_environment_path(project.namespace, project, environment) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/new" do subject { new_namespace_project_environment_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/container_registry" do @@ -371,14 +358,14 @@ describe "Private Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 985663e7c98..bed9e92fcb6 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -5,19 +5,6 @@ describe "Public Project Access", feature: true do let(:project) { create(:project, :public) } - let(:owner) { project.owner } - let(:master) { create(:user) } - let(:developer) { create(:user) } - let(:reporter) { create(:user) } - let(:guest) { create(:user) } - - before do - project.team << [master, :master] - project.team << [developer, :developer] - project.team << [reporter, :reporter] - project.team << [guest, :guest] - end - describe "Project should be public" do describe '#public?' do subject { project.public? } @@ -28,114 +15,114 @@ describe "Public Project Access", feature: true do describe "GET /:project_path" do subject { namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/tree/master" do subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/commits/master" do subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/commit/:sha" do subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/compare" do subject { namespace_project_compare_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/project_members" do subject { namespace_project_project_members_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } - it { is_expected.to be_allowed_for :external } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:visitor) } + it { is_expected.to be_allowed_for(:external) } end describe "GET /:project_path/pipelines" do subject { namespace_project_pipelines_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/pipelines/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } subject { namespace_project_pipeline_path(project.namespace, project, pipeline) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/builds" do @@ -144,29 +131,29 @@ describe "Public Project Access", feature: true do context "when allowed for public" do before { project.update(public_builds: true) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end context "when disallowed for public" do before { project.update(public_builds: false) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end @@ -178,73 +165,73 @@ describe "Public Project Access", feature: true do context "when allowed for public" do before { project.update(public_builds: true) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end context "when disallowed for public" do before { project.update(public_builds: false) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end end describe "GET /:project_path/environments" do subject { namespace_project_environments_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/:id" do let(:environment) { create(:environment, project: project) } subject { namespace_project_environment_path(project.namespace, project, environment) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/environments/new" do subject { new_namespace_project_environment_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/blob" do @@ -252,127 +239,127 @@ describe "Public Project Access", feature: true do subject { namespace_project_blob_path(project.namespace, project, File.join(commit.id, '.gitignore')) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/edit" do subject { edit_namespace_project_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/deploy_keys" do subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/issues" do subject { namespace_project_issues_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/issues/:id/edit" do let(:issue) { create(:issue, project: project) } subject { edit_namespace_project_issue_path(project.namespace, project, issue) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/snippets" do subject { namespace_project_snippets_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/snippets/new" do subject { new_namespace_project_snippet_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/merge_requests" do subject { namespace_project_merge_requests_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/merge_requests/new" do subject { new_namespace_project_merge_request_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/branches" do @@ -383,15 +370,15 @@ describe "Public Project Access", feature: true do allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/tags" do @@ -402,29 +389,29 @@ describe "Public Project Access", feature: true do allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end describe "GET /:project_path/hooks" do subject { namespace_project_hooks_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_denied_for developer } - it { is_expected.to be_denied_for reporter } - it { is_expected.to be_denied_for guest } - it { is_expected.to be_denied_for :user } - it { is_expected.to be_denied_for :external } - it { is_expected.to be_denied_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_denied_for(:developer).of(project) } + it { is_expected.to be_denied_for(:reporter).of(project) } + it { is_expected.to be_denied_for(:guest).of(project) } + it { is_expected.to be_denied_for(:user) } + it { is_expected.to be_denied_for(:external) } + it { is_expected.to be_denied_for(:visitor) } end describe "GET /:project_path/container_registry" do @@ -435,14 +422,14 @@ describe "Public Project Access", feature: true do subject { namespace_project_container_registry_index_path(project.namespace, project) } - it { is_expected.to be_allowed_for :admin } - it { is_expected.to be_allowed_for owner } - it { is_expected.to be_allowed_for master } - it { is_expected.to be_allowed_for developer } - it { is_expected.to be_allowed_for reporter } - it { is_expected.to be_allowed_for guest } - it { is_expected.to be_allowed_for :user } - it { is_expected.to be_allowed_for :external } - it { is_expected.to be_allowed_for :visitor } + it { is_expected.to be_allowed_for(:admin) } + it { is_expected.to be_allowed_for(:owner).of(project) } + it { is_expected.to be_allowed_for(:master).of(project) } + it { is_expected.to be_allowed_for(:developer).of(project) } + it { is_expected.to be_allowed_for(:reporter).of(project) } + it { is_expected.to be_allowed_for(:guest).of(project) } + it { is_expected.to be_allowed_for(:user) } + it { is_expected.to be_allowed_for(:external) } + it { is_expected.to be_allowed_for(:visitor) } end end diff --git a/spec/features/snippets/create_snippet_spec.rb b/spec/features/snippets/create_snippet_spec.rb new file mode 100644 index 00000000000..cb95e7828db --- /dev/null +++ b/spec/features/snippets/create_snippet_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +feature 'Create Snippet', feature: true do + before do + login_as :user + visit new_snippet_path + end + + scenario 'Authenticated user creates a snippet' do + fill_in 'personal_snippet_title', with: 'My Snippet Title' + page.within('.file-editor') do + find(:xpath, "//input[@id='personal_snippet_content']").set 'Hello World!' + end + + click_button 'Create snippet' + + expect(page).to have_content('My Snippet Title') + expect(page).to have_content('Hello World!') + end +end diff --git a/spec/features/variables_spec.rb b/spec/features/variables_spec.rb index d7880d5778f..ff30ffd7820 100644 --- a/spec/features/variables_spec.rb +++ b/spec/features/variables_spec.rb @@ -29,6 +29,31 @@ describe 'Project variables', js: true do end end + it 'reveals and hides new variable' do + fill_in('variable_key', with: 'key') + fill_in('variable_value', with: 'key value') + click_button('Add new variable') + + page.within('.variables-table') do + expect(page).to have_content('key') + expect(page).to have_content('******') + end + + click_button('Reveal Values') + + page.within('.variables-table') do + expect(page).to have_content('key') + expect(page).to have_content('key value') + end + + click_button('Hide Values') + + page.within('.variables-table') do + expect(page).to have_content('key') + expect(page).to have_content('******') + end + end + it 'deletes variable' do page.within('.variables-table') do find('.btn-variable-delete').click diff --git a/spec/helpers/issuables_helper_spec.rb b/spec/helpers/issuables_helper_spec.rb index 62cc10f579a..a4f08dc4af0 100644 --- a/spec/helpers/issuables_helper_spec.rb +++ b/spec/helpers/issuables_helper_spec.rb @@ -114,4 +114,25 @@ describe IssuablesHelper do end end end + + describe '#issuable_filter_present?' do + it 'returns true when any key is present' do + allow(helper).to receive(:params).and_return( + ActionController::Parameters.new(milestone_title: 'Velit consectetur asperiores natus delectus.', + project_id: 'gitlabhq', + scope: 'all') + ) + + expect(helper.issuable_filter_present?).to be_truthy + end + + it 'returns false when no key is present' do + allow(helper).to receive(:params).and_return( + ActionController::Parameters.new(project_id: 'gitlabhq', + scope: 'all') + ) + + expect(helper.issuable_filter_present?).to be_falsey + end + end end diff --git a/spec/javascripts/build_spec.js.es6 b/spec/javascripts/build_spec.js.es6 index 4208e076e96..3983cad4c13 100644 --- a/spec/javascripts/build_spec.js.es6 +++ b/spec/javascripts/build_spec.js.es6 @@ -8,184 +8,177 @@ //= require jquery.nicescroll //= require turbolinks -(() => { - describe('Build', () => { - fixture.preload('build.html'); +describe('Build', () => { + const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1`; + // see spec/factories/ci/builds.rb + const BUILD_TRACE = 'BUILD TRACE'; + // see lib/ci/ansi2html.rb + const INITIAL_BUILD_TRACE_STATE = window.btoa(JSON.stringify({ + offset: BUILD_TRACE.length, n_open_tags: 0, fg_color: null, bg_color: null, style_mask: 0, + })); + + fixture.preload('builds/build-with-artifacts.html.raw'); + + beforeEach(() => { + fixture.load('builds/build-with-artifacts.html.raw'); + spyOn($, 'ajax'); + }); + + describe('constructor', () => { + beforeEach(() => { + jasmine.clock().install(); + }); - beforeEach(function () { - fixture.load('build.html'); - spyOn($, 'ajax'); + afterEach(() => { + jasmine.clock().uninstall(); }); - describe('constructor', () => { + describe('setup', () => { beforeEach(function () { - jasmine.clock().install(); + this.build = new Build(); }); - afterEach(() => { - jasmine.clock().uninstall(); + it('copies build options', function () { + expect(this.build.pageUrl).toBe(BUILD_URL); + expect(this.build.buildUrl).toBe(`${BUILD_URL}.json`); + expect(this.build.buildStatus).toBe('success'); + expect(this.build.buildStage).toBe('test'); + expect(this.build.state).toBe(INITIAL_BUILD_TRACE_STATE); }); - describe('setup', function () { - const removeDate = new Date(); - removeDate.setUTCFullYear(removeDate.getUTCFullYear() + 1); - // give the test three days to run - removeDate.setTime(removeDate.getTime() + (3 * 24 * 60 * 60 * 1000)); + it('only shows the jobs matching the current stage', () => { + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); - beforeEach(function () { - const removeDateElement = document.querySelector('.js-artifacts-remove'); - removeDateElement.innerText = removeDate.toString(); + it('selects the current stage in the build dropdown menu', () => { + expect($('.stage-selection').text()).toBe('test'); + }); - this.build = new Build(); - }); + it('updates the jobs when the build dropdown changes', () => { + $('.stage-item:contains("build")').click(); - it('copies build options', function () { - expect(this.build.pageUrl).toBe('http://example.com/root/test-build/builds/2'); - expect(this.build.buildUrl).toBe('http://example.com/root/test-build/builds/2.json'); - expect(this.build.buildStatus).toBe('passed'); - expect(this.build.buildStage).toBe('test'); - expect(this.build.state).toBe('buildstate'); - }); + expect($('.stage-selection').text()).toBe('build'); + expect($('.build-job[data-stage="build"]').is(':visible')).toBe(true); + expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false); + expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); + }); - it('only shows the jobs matching the current stage', function () { - expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false); - expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true); - expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); - }); + it('displays the remove date correctly', () => { + const removeDateElement = document.querySelector('.js-artifacts-remove'); + expect(removeDateElement.innerText.trim()).toBe('1 year'); + }); + }); - it('selects the current stage in the build dropdown menu', function () { - expect($('.stage-selection').text()).toBe('test'); - }); + describe('initial build trace', () => { + beforeEach(() => { + new Build(); + }); - it('updates the jobs when the build dropdown changes', function () { - $('.stage-item:contains("build")').click(); + it('displays the initial build trace', () => { + expect($.ajax.calls.count()).toBe(1); + const [{ url, dataType, success, context }] = $.ajax.calls.argsFor(0); + expect(url).toBe(`${BUILD_URL}.json`); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); - expect($('.stage-selection').text()).toBe('build'); - expect($('.build-job[data-stage="build"]').is(':visible')).toBe(true); - expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false); - expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false); - }); + success.call(context, { trace_html: '<span>Example</span>', status: 'running' }); - it('displays the remove date correctly', function () { - const removeDateElement = document.querySelector('.js-artifacts-remove'); - expect(removeDateElement.innerText.trim()).toBe('1 year'); - }); + expect($('#build-trace .js-build-output').text()).toMatch(/Example/); }); - describe('initial build trace', function () { - beforeEach(function () { - new Build(); - }); + it('removes the spinner', () => { + const [{ success, context }] = $.ajax.calls.argsFor(0); + success.call(context, { trace_html: '<span>Example</span>', status: 'success' }); - it('displays the initial build trace', function () { - expect($.ajax.calls.count()).toBe(1); - const [{ url, dataType, success, context }] = $.ajax.calls.argsFor(0); - expect(url).toBe('http://example.com/root/test-build/builds/2.json'); - expect(dataType).toBe('json'); - expect(success).toEqual(jasmine.any(Function)); + expect($('.js-build-refresh').length).toBe(0); + }); + }); - success.call(context, { trace_html: '<span>Example</span>', status: 'running' }); + describe('running build', () => { + beforeEach(function () { + $('.js-build-options').data('buildStatus', 'running'); + this.build = new Build(); + spyOn(this.build, 'location').and.returnValue(BUILD_URL); + }); - expect($('#build-trace .js-build-output').text()).toMatch(/Example/); + it('updates the build trace on an interval', function () { + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(2); + let [{ url, dataType, success, context }] = $.ajax.calls.argsFor(1); + expect(url).toBe( + `${BUILD_URL}/trace.json?state=${encodeURIComponent(INITIAL_BUILD_TRACE_STATE)}`, + ); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: '<span>Update<span>', + status: 'running', + state: 'newstate', + append: true, }); - it('removes the spinner', function () { - const [{ success, context }] = $.ajax.calls.argsFor(0); - success.call(context, { trace_html: '<span>Example</span>', status: 'success' }); + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); + expect(this.build.state).toBe('newstate'); - expect($('.js-build-refresh').length).toBe(0); + jasmine.clock().tick(4001); + + expect($.ajax.calls.count()).toBe(3); + [{ url, dataType, success, context }] = $.ajax.calls.argsFor(2); + expect(url).toBe(`${BUILD_URL}/trace.json?state=newstate`); + expect(dataType).toBe('json'); + expect(success).toEqual(jasmine.any(Function)); + + success.call(context, { + html: '<span>More</span>', + status: 'running', + state: 'finalstate', + append: true, }); + + expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); + expect(this.build.state).toBe('finalstate'); }); - describe('running build', function () { - beforeEach(function () { - $('.js-build-options').data('buildStatus', 'running'); - this.build = new Build(); - spyOn(this.build, 'location') - .and.returnValue('http://example.com/root/test-build/builds/2'); + it('replaces the entire build trace', () => { + jasmine.clock().tick(4001); + let [{ success, context }] = $.ajax.calls.argsFor(1); + success.call(context, { + html: '<span>Update</span>', + status: 'running', + append: true, }); - it('updates the build trace on an interval', function () { - jasmine.clock().tick(4001); - - expect($.ajax.calls.count()).toBe(2); - let [{ url, dataType, success, context }] = $.ajax.calls.argsFor(1); - expect(url).toBe( - 'http://example.com/root/test-build/builds/2/trace.json?state=buildstate' - ); - expect(dataType).toBe('json'); - expect(success).toEqual(jasmine.any(Function)); - - success.call(context, { - html: '<span>Update<span>', - status: 'running', - state: 'newstate', - append: true, - }); - - expect($('#build-trace .js-build-output').text()).toMatch(/Update/); - expect(this.build.state).toBe('newstate'); - - jasmine.clock().tick(4001); - - expect($.ajax.calls.count()).toBe(3); - [{ url, dataType, success, context }] = $.ajax.calls.argsFor(2); - expect(url).toBe( - 'http://example.com/root/test-build/builds/2/trace.json?state=newstate' - ); - expect(dataType).toBe('json'); - expect(success).toEqual(jasmine.any(Function)); - - success.call(context, { - html: '<span>More</span>', - status: 'running', - state: 'finalstate', - append: true, - }); - - expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/); - expect(this.build.state).toBe('finalstate'); - }); + expect($('#build-trace .js-build-output').text()).toMatch(/Update/); - it('replaces the entire build trace', function () { - jasmine.clock().tick(4001); - let [{ success, context }] = $.ajax.calls.argsFor(1); - success.call(context, { - html: '<span>Update</span>', - status: 'running', - append: true, - }); - - expect($('#build-trace .js-build-output').text()).toMatch(/Update/); - - jasmine.clock().tick(4001); - [{ success, context }] = $.ajax.calls.argsFor(2); - success.call(context, { - html: '<span>Different</span>', - status: 'running', - append: false, - }); - - expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); - expect($('#build-trace .js-build-output').text()).toMatch(/Different/); + jasmine.clock().tick(4001); + [{ success, context }] = $.ajax.calls.argsFor(2); + success.call(context, { + html: '<span>Different</span>', + status: 'running', + append: false, }); - it('reloads the page when the build is done', function () { - spyOn(Turbolinks, 'visit'); + expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/); + expect($('#build-trace .js-build-output').text()).toMatch(/Different/); + }); - jasmine.clock().tick(4001); - const [{ success, context }] = $.ajax.calls.argsFor(1); - success.call(context, { - html: '<span>Final</span>', - status: 'passed', - append: true, - }); + it('reloads the page when the build is done', () => { + spyOn(Turbolinks, 'visit'); - expect(Turbolinks.visit).toHaveBeenCalledWith( - 'http://example.com/root/test-build/builds/2' - ); + jasmine.clock().tick(4001); + const [{ success, context }] = $.ajax.calls.argsFor(1); + success.call(context, { + html: '<span>Final</span>', + status: 'passed', + append: true, }); + + expect(Turbolinks.visit).toHaveBeenCalledWith(BUILD_URL); }); }); }); -})(); +}); diff --git a/spec/javascripts/environments/environment_actions_spec.js.es6 b/spec/javascripts/environments/environment_actions_spec.js.es6 index c9ac7a73fd0..76e81233e89 100644 --- a/spec/javascripts/environments/environment_actions_spec.js.es6 +++ b/spec/javascripts/environments/environment_actions_spec.js.es6 @@ -28,10 +28,10 @@ describe('Actions Component', () => { }); expect( - component.$el.querySelectorAll('.dropdown-menu li').length + component.$el.querySelectorAll('.dropdown-menu li').length, ).toEqual(actionsMock.length); expect( - component.$el.querySelector('.dropdown-menu li a').getAttribute('href') + component.$el.querySelector('.dropdown-menu li a').getAttribute('href'), ).toEqual(actionsMock[0].play_path); }); }); diff --git a/spec/javascripts/environments/environment_item_spec.js.es6 b/spec/javascripts/environments/environment_item_spec.js.es6 index 3c15e3b7719..14e90a9dd1b 100644 --- a/spec/javascripts/environments/environment_item_spec.js.es6 +++ b/spec/javascripts/environments/environment_item_spec.js.es6 @@ -141,18 +141,18 @@ describe('Environment item', () => { describe('With deployment', () => { it('should render deployment internal id', () => { expect( - component.$el.querySelector('.deployment-column span').textContent + component.$el.querySelector('.deployment-column span').textContent, ).toContain(environment.last_deployment.iid); expect( - component.$el.querySelector('.deployment-column span').textContent + component.$el.querySelector('.deployment-column span').textContent, ).toContain('#'); }); describe('With user information', () => { it('should render user avatar with link to profile', () => { expect( - component.$el.querySelector('.js-deploy-user-container').getAttribute('href') + component.$el.querySelector('.js-deploy-user-container').getAttribute('href'), ).toEqual(environment.last_deployment.user.web_url); }); }); @@ -160,13 +160,13 @@ describe('Environment item', () => { describe('With build url', () => { it('Should link to build url provided', () => { expect( - component.$el.querySelector('.build-link').getAttribute('href') + component.$el.querySelector('.build-link').getAttribute('href'), ).toEqual(environment.last_deployment.deployable.build_path); }); it('Should render deployable name and id', () => { expect( - component.$el.querySelector('.build-link').getAttribute('href') + component.$el.querySelector('.build-link').getAttribute('href'), ).toEqual(environment.last_deployment.deployable.build_path); }); }); @@ -174,7 +174,7 @@ describe('Environment item', () => { describe('With commit information', () => { it('should render commit component', () => { expect( - component.$el.querySelector('.js-commit-component') + component.$el.querySelector('.js-commit-component'), ).toBeDefined(); }); }); @@ -183,7 +183,7 @@ describe('Environment item', () => { describe('With manual actions', () => { it('Should render actions component', () => { expect( - component.$el.querySelector('.js-manual-actions-container') + component.$el.querySelector('.js-manual-actions-container'), ).toBeDefined(); }); }); @@ -191,7 +191,7 @@ describe('Environment item', () => { describe('With external URL', () => { it('should render external url component', () => { expect( - component.$el.querySelector('.js-external-url-container') + component.$el.querySelector('.js-external-url-container'), ).toBeDefined(); }); }); @@ -199,7 +199,7 @@ describe('Environment item', () => { describe('With stop action', () => { it('Should render stop action component', () => { expect( - component.$el.querySelector('.js-stop-component-container') + component.$el.querySelector('.js-stop-component-container'), ).toBeDefined(); }); }); @@ -207,7 +207,7 @@ describe('Environment item', () => { describe('With retry action', () => { it('Should render rollback component', () => { expect( - component.$el.querySelector('.js-rollback-component-container') + component.$el.querySelector('.js-rollback-component-container'), ).toBeDefined(); }); }); diff --git a/spec/javascripts/environments/environments_store_spec.js.es6 b/spec/javascripts/environments/environments_store_spec.js.es6 index 9b0b3cb1c65..17c00acf63e 100644 --- a/spec/javascripts/environments/environments_store_spec.js.es6 +++ b/spec/javascripts/environments/environments_store_spec.js.es6 @@ -5,11 +5,11 @@ //= require ./mock_data (() => { - beforeEach(() => { - gl.environmentsList.EnvironmentsStore.create(); - }); - describe('Store', () => { + beforeEach(() => { + gl.environmentsList.EnvironmentsStore.create(); + }); + it('should start with a blank state', () => { expect(gl.environmentsList.EnvironmentsStore.state.environments.length).toBe(0); expect(gl.environmentsList.EnvironmentsStore.state.stoppedCounter).toBe(0); diff --git a/spec/javascripts/extensions/array_spec.js b/spec/javascripts/extensions/array_spec.js deleted file mode 100644 index c56e6c7789b..00000000000 --- a/spec/javascripts/extensions/array_spec.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable space-before-function-paren, no-var, padded-blocks */ - -/*= require extensions/array */ - -(function() { - describe('Array extensions', function() { - describe('first', function() { - return it('returns the first item', function() { - var arr; - arr = [0, 1, 2, 3, 4, 5]; - return expect(arr.first()).toBe(0); - }); - }); - return describe('last', function() { - return it('returns the last item', function() { - var arr; - arr = [0, 1, 2, 3, 4, 5]; - return expect(arr.last()).toBe(5); - }); - }); - }); - -}).call(this); diff --git a/spec/javascripts/extensions/array_spec.js.es6 b/spec/javascripts/extensions/array_spec.js.es6 new file mode 100644 index 00000000000..2ec759c8e80 --- /dev/null +++ b/spec/javascripts/extensions/array_spec.js.es6 @@ -0,0 +1,46 @@ +/* eslint-disable space-before-function-paren, no-var, padded-blocks */ + +/*= require extensions/array */ + +(function() { + describe('Array extensions', function() { + describe('first', function() { + return it('returns the first item', function() { + var arr; + arr = [0, 1, 2, 3, 4, 5]; + return expect(arr.first()).toBe(0); + }); + }); + describe('last', function() { + return it('returns the last item', function() { + var arr; + arr = [0, 1, 2, 3, 4, 5]; + return expect(arr.last()).toBe(5); + }); + }); + + describe('find', function () { + beforeEach(() => { + this.arr = [0, 1, 2, 3, 4, 5]; + }); + + it('returns the item that first passes the predicate function', () => { + expect(this.arr.find(item => item === 2)).toBe(2); + }); + + it('returns undefined if no items pass the predicate function', () => { + expect(this.arr.find(item => item === 6)).not.toBeDefined(); + }); + + it('error when called on undefined or null', () => { + expect(Array.prototype.find.bind(undefined, item => item === 1)).toThrow(); + expect(Array.prototype.find.bind(null, item => item === 1)).toThrow(); + }); + + it('error when predicate is not a function', () => { + expect(Array.prototype.find.bind(this.arr, 1)).toThrow(); + }); + }); + }); + +}).call(this); diff --git a/spec/javascripts/fixtures/build.html.haml b/spec/javascripts/fixtures/build.html.haml deleted file mode 100644 index 06b49516e5c..00000000000 --- a/spec/javascripts/fixtures/build.html.haml +++ /dev/null @@ -1,62 +0,0 @@ -.build-page - .prepend-top-default - .autoscroll-container - %button.btn.btn-success.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}} enable autoscroll - #js-build-scroll.scroll-controls - %a.btn{href: '#build-trace'} - %i.fa.fa-angle-up - %a.btn{href: '#down-build-trace'} - %i.fa.fa-angle-down - %pre.build-trace#build-trace - %code.bash.js-build-output - %i.fa.fa-refresh.fa-spin.js-build-refresh - -%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar - .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default - Build - %strong #1 - %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } - %i.fa.fa-angle-double-right - .blocks-container - .dropdown.build-dropdown - .title Stage - %button.dropdown-menu-toggle{type: 'button', 'data-toggle' => 'dropdown'} - %span.stage-selection More - %i.fa.fa-caret-down - %ul.dropdown-menu - %li - %a.stage-item build - %li - %a.stage-item test - %li - %a.stage-item deploy - .builds-container - .build-job{data: {stage: 'build'}} - %a{href: 'http://example.com/root/test-build/builds/1'} - %i.fa.fa-check - %i.fa.fa-check-circle-o - %span - Setup - .build-job{data: {stage: 'test'}} - %a{href: 'http://example.com/root/test-build/builds/2'} - %i.fa.fa-check - %i.fa.fa-check-circle-o - %span - Tests - .build-job{data: {stage: 'deploy'}} - %a{href: 'http://example.com/root/test-build/builds/3'} - %i.fa.fa-check - %i.fa.fa-check-circle-o - %span - Deploy - -.js-build-options{ data: { page_url: 'http://example.com/root/test-build/builds/2', - build_url: 'http://example.com/root/test-build/builds/2.json', - build_status: 'passed', - build_stage: 'test', - log_state: 'buildstate' }} - -%p.build-detail-row - The artifacts will be removed in - %span.js-artifacts-remove - 2016-12-19 09:02:12 UTC diff --git a/spec/javascripts/fixtures/builds.rb b/spec/javascripts/fixtures/builds.rb new file mode 100644 index 00000000000..978e25a1c32 --- /dev/null +++ b/spec/javascripts/fixtures/builds.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe Projects::BuildsController, '(JavaScript fixtures)', type: :controller do + include JavaScriptFixturesHelpers + + let(:admin) { create(:admin) } + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project_empty_repo, namespace: namespace, path: 'builds-project') } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let!(:build_with_artifacts) { create(:ci_build, :success, :artifacts, :trace, pipeline: pipeline, stage: 'test', artifacts_expire_at: Time.now + 18.months) } + let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline, stage: 'build') } + let!(:pending_build) { create(:ci_build, :pending, pipeline: pipeline, stage: 'deploy') } + + render_views + + before(:all) do + clean_frontend_fixtures('builds/') + end + + before(:each) do + sign_in(admin) + end + + it 'builds/build-with-artifacts.html.raw' do |example| + get :show, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + id: build_with_artifacts.to_param + + expect(response).to be_success + store_frontend_fixture(response, example.description) + end +end diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb index d95eb851421..c10784fe5ae 100644 --- a/spec/javascripts/fixtures/issues.rb +++ b/spec/javascripts/fixtures/issues.rb @@ -4,7 +4,8 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller include JavaScriptFixturesHelpers let(:admin) { create(:admin) } - let(:project) { create(:project_empty_repo) } + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project_empty_repo, namespace: namespace, path: 'issues-project') } render_views diff --git a/spec/javascripts/fixtures/zen_mode.html.haml b/spec/javascripts/fixtures/zen_mode.html.haml deleted file mode 100644 index cb906a7feaa..00000000000 --- a/spec/javascripts/fixtures/zen_mode.html.haml +++ /dev/null @@ -1,8 +0,0 @@ -.md-area - .zen-backdrop - %textarea#note_note.js-gfm-input.markdown-area - %a.js-zen-enter(tabindex="-1" href="#") - %i.fa.fa-expand - Edit in fullscreen - %a.js-zen-leave(tabindex="-1" href="#") - %i.fa.fa-compress diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js index beef46122ab..14af6644de1 100644 --- a/spec/javascripts/issue_spec.js +++ b/spec/javascripts/issue_spec.js @@ -74,7 +74,7 @@ it('submits an ajax request on tasklist:changed', function() { spyOn(jQuery, 'ajax').and.callFake(function(req) { expect(req.type).toBe('PATCH'); - expect(req.url).toBe('https://fixture.invalid/namespace3/project3/issues/1.json'); + expect(req.url).toBe(gl.TEST_HOST + '/frontend-fixtures/issues-project/issues/1.json'); // eslint-disable-line prefer-template expect(req.data.issue.description).not.toBe(null); }); diff --git a/spec/javascripts/smart_interval_spec.js.es6 b/spec/javascripts/smart_interval_spec.js.es6 index 651d1f0f975..ed6166a25a8 100644 --- a/spec/javascripts/smart_interval_spec.js.es6 +++ b/spec/javascripts/smart_interval_spec.js.es6 @@ -37,7 +37,7 @@ const intervalConfig = this.smartInterval.cfg; const iterationCount = 4; const maxIntervalAfterIterations = intervalConfig.startingInterval * - Math.pow(intervalConfig.incrementByFactorOf, (iterationCount - 1)); // 40 + (intervalConfig.incrementByFactorOf ** (iterationCount - 1)); // 40 const currentInterval = interval.getCurrentInterval(); // Provide some flexibility for performance of testing environment diff --git a/spec/javascripts/spec_helper.js b/spec/javascripts/spec_helper.js index 8a64de4dd43..831dfada952 100644 --- a/spec/javascripts/spec_helper.js +++ b/spec/javascripts/spec_helper.js @@ -41,3 +41,8 @@ }).call(this); + +// defined in ActionDispatch::TestRequest +// see https://github.com/rails/rails/blob/v4.2.7.1/actionpack/lib/action_dispatch/testing/test_request.rb#L7 +window.gl = window.gl || {}; +gl.TEST_HOST = 'http://test.host'; diff --git a/spec/javascripts/vue_common_components/commit_spec.js.es6 b/spec/javascripts/vue_common_components/commit_spec.js.es6 index 0e3b82967c1..b1dbc8bd5fa 100644 --- a/spec/javascripts/vue_common_components/commit_spec.js.es6 +++ b/spec/javascripts/vue_common_components/commit_spec.js.es6 @@ -74,26 +74,26 @@ describe('Commit component', () => { describe('Given commit title and author props', () => { it('Should render a link to the author profile', () => { expect( - component.$el.querySelector('.commit-title .avatar-image-container').getAttribute('href') + component.$el.querySelector('.commit-title .avatar-image-container').getAttribute('href'), ).toEqual(props.author.web_url); }); it('Should render the author avatar with title and alt attributes', () => { expect( - component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('title') + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('title'), ).toContain(props.author.username); expect( - component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('alt') + component.$el.querySelector('.commit-title .avatar-image-container img').getAttribute('alt'), ).toContain(`${props.author.username}'s avatar`); }); }); it('should render the commit title', () => { expect( - component.$el.querySelector('a.commit-row-message').getAttribute('href') + component.$el.querySelector('a.commit-row-message').getAttribute('href'), ).toEqual(props.commit_url); expect( - component.$el.querySelector('a.commit-row-message').textContent + component.$el.querySelector('a.commit-row-message').textContent, ).toContain(props.title); }); }); @@ -119,7 +119,7 @@ describe('Commit component', () => { }); expect( - component.$el.querySelector('.commit-title span').textContent + component.$el.querySelector('.commit-title span').textContent, ).toContain('Cant find HEAD commit for this branch'); }); }); diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js index a18e8aee9b1..b9acaaa5a0d 100644 --- a/spec/javascripts/zen_mode_spec.js +++ b/spec/javascripts/zen_mode_spec.js @@ -6,9 +6,10 @@ var enterZen, escapeKeydown, exitZen; describe('ZenMode', function() { - fixture.preload('zen_mode.html'); + var fixtureName = 'issues/open-issue.html.raw'; + fixture.preload(fixtureName); beforeEach(function() { - fixture.load('zen_mode.html'); + fixture.load(fixtureName); spyOn(Dropzone, 'forElement').and.callFake(function() { return { enable: function() { @@ -60,11 +61,11 @@ }); enterZen = function() { - return $('a.js-zen-enter').click(); + return $('.js-zen-enter').click(); }; exitZen = function() { // Ohmmmmmmm - return $('a.js-zen-leave').click(); + return $('.js-zen-leave').click(); }; escapeKeydown = function() { diff --git a/spec/lib/gitlab/chat_commands/issue_search_spec.rb b/spec/lib/gitlab/chat_commands/issue_search_spec.rb new file mode 100644 index 00000000000..24c06a967fa --- /dev/null +++ b/spec/lib/gitlab/chat_commands/issue_search_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' + +describe Gitlab::ChatCommands::IssueSearch, service: true do + describe '#execute' do + let!(:issue) { create(:issue, title: 'find me') } + let!(:confidential) { create(:issue, :confidential, project: project, title: 'mepmep find') } + let(:project) { issue.project } + let(:user) { issue.author } + let(:regex_match) { described_class.match("issue search find") } + + subject do + described_class.new(project, user).execute(regex_match) + end + + context 'when the user has no access' do + it 'only returns the open issues' do + expect(subject).not_to include(confidential) + end + end + + context 'the user has access' do + before do + project.team << [user, :master] + end + + it 'returns all results' do + expect(subject).to include(confidential, issue) + end + end + + context 'without hits on the query' do + it 'returns an empty collection' do + expect(subject).to be_empty + end + end + end + + describe 'self.match' do + let(:query) { "my search keywords" } + it 'matches the query' do + match = described_class.match("issue search #{query}") + + expect(match[:query]).to eq(query) + end + end +end diff --git a/spec/lib/gitlab/chat_commands/issue_show_spec.rb b/spec/lib/gitlab/chat_commands/issue_show_spec.rb index 331a4604e9b..2eab73e49e5 100644 --- a/spec/lib/gitlab/chat_commands/issue_show_spec.rb +++ b/spec/lib/gitlab/chat_commands/issue_show_spec.rb @@ -19,6 +19,14 @@ describe Gitlab::ChatCommands::IssueShow, service: true do it 'returns the issue' do expect(subject.iid).to be issue.iid end + + context 'when its reference is given' do + let(:regex_match) { described_class.match("issue show #{issue.to_reference}") } + + it 'shows the issue' do + expect(subject.iid).to be issue.iid + end + end end context 'the issue does not exist' do diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb new file mode 100644 index 00000000000..c863a5f04cc --- /dev/null +++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Gitlab::Diff::FileCollection::MergeRequestDiff do + let(:merge_request) { create :merge_request } + + it 'does not hightlight binary files' do + allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(double("text?" => false)) + + expect_any_instance_of(Gitlab::Diff::File).not_to receive(:highlighted_diff_lines) + + described_class.new(merge_request.merge_request_diff, diff_options: nil).diff_files + end +end diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb index a0fdad87eee..3cd9863ec6a 100644 --- a/spec/lib/gitlab/project_search_results_spec.rb +++ b/spec/lib/gitlab/project_search_results_spec.rb @@ -65,6 +65,14 @@ describe Gitlab::ProjectSearchResults, lib: true do end end + it 'does not list issues on private projects' do + issue = create(:issue, project: project) + + results = described_class.new(user, project, issue.title) + + expect(results.objects('issues')).not_to include issue + end + describe 'confidential issues' do let(:query) { 'issue' } let(:author) { create(:user) } @@ -72,6 +80,7 @@ describe Gitlab::ProjectSearchResults, lib: true do let(:non_member) { create(:user) } let(:member) { create(:user) } let(:admin) { create(:admin) } + let(:project) { create(:empty_project, :internal) } let!(:issue) { create(:issue, project: project, title: 'Issue 1') } let!(:security_issue_1) { create(:issue, :confidential, project: project, title: 'Security issue 1', author: author) } let!(:security_issue_2) { create(:issue, :confidential, title: 'Security issue 2', project: project, assignee: assignee) } diff --git a/spec/lib/gitlab/search_results_spec.rb b/spec/lib/gitlab/search_results_spec.rb index dfbefad6367..f23e3522625 100644 --- a/spec/lib/gitlab/search_results_spec.rb +++ b/spec/lib/gitlab/search_results_spec.rb @@ -12,35 +12,48 @@ describe Gitlab::SearchResults do let!(:milestone) { create(:milestone, project: project, title: 'foo') } let(:results) { described_class.new(user, Project.all, 'foo') } - describe '#projects_count' do - it 'returns the total amount of projects' do - expect(results.projects_count).to eq(1) + context 'as a user with access' do + before do + project.team << [user, :developer] end - end - describe '#issues_count' do - it 'returns the total amount of issues' do - expect(results.issues_count).to eq(1) + describe '#projects_count' do + it 'returns the total amount of projects' do + expect(results.projects_count).to eq(1) + end end - end - describe '#merge_requests_count' do - it 'returns the total amount of merge requests' do - expect(results.merge_requests_count).to eq(1) + describe '#issues_count' do + it 'returns the total amount of issues' do + expect(results.issues_count).to eq(1) + end + end + + describe '#merge_requests_count' do + it 'returns the total amount of merge requests' do + expect(results.merge_requests_count).to eq(1) + end end - end - describe '#milestones_count' do - it 'returns the total amount of milestones' do - expect(results.milestones_count).to eq(1) + describe '#milestones_count' do + it 'returns the total amount of milestones' do + expect(results.milestones_count).to eq(1) + end end end + it 'does not list issues on private projects' do + private_project = create(:empty_project, :private) + issue = create(:issue, project: private_project, title: 'foo') + + expect(results.objects('issues')).not_to include issue + end + describe 'confidential issues' do - let(:project_1) { create(:empty_project) } - let(:project_2) { create(:empty_project) } - let(:project_3) { create(:empty_project) } - let(:project_4) { create(:empty_project) } + let(:project_1) { create(:empty_project, :internal) } + let(:project_2) { create(:empty_project, :internal) } + let(:project_3) { create(:empty_project, :internal) } + let(:project_4) { create(:empty_project, :internal) } let(:query) { 'issue' } let(:limit_projects) { Project.where(id: [project_1.id, project_2.id, project_3.id]) } let(:author) { create(:user) } diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 932a5dc4862..b692142713f 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -50,7 +50,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) + stub_application_setting(email_author_in_body: true) end it 'contains a link to note author' do @@ -229,7 +229,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) + stub_application_setting(email_author_in_body: true) end it 'contains a link to note author' do @@ -607,7 +607,7 @@ describe Notify do context 'when enabled email_author_in_body' do before do - allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true) + stub_application_setting(email_author_in_body: true) end it 'contains a link to note author' do @@ -686,6 +686,79 @@ describe Notify do end end end + + context 'items that are noteable, emails for a note on a diff' do + let(:note_author) { create(:user, name: 'author_name') } + + before :each do + allow(Note).to receive(:find).with(note.id).and_return(note) + end + + shared_examples 'a note email on a diff' do |model| + let(:note) { create(model, project: project, author: note_author) } + + it "includes diffs with character-level highlighting" do + is_expected.to have_body_text /<span class=\"p\">}<\/span><\/span>/ + end + + it 'contains a link to the diff file' do + is_expected.to have_body_text /#{note.diff_file.file_path}/ + end + + it_behaves_like 'it should have Gmail Actions links' + + it 'is sent as the author' do + sender = subject.header[:from].addrs[0] + expect(sender.display_name).to eq(note_author.name) + expect(sender.address).to eq(gitlab_sender) + end + + it 'is sent to the given recipient' do + is_expected.to deliver_to recipient.notification_email + end + + it 'contains the message from the note' do + is_expected.to have_body_text /#{note.note}/ + end + + it 'does not contain note author' do + is_expected.not_to have_body_text /wrote\:/ + end + + context 'when enabled email_author_in_body' do + before do + stub_application_setting(email_author_in_body: true) + end + + it 'contains a link to note author' do + is_expected.to have_body_text note.author_name + is_expected.to have_body_text /wrote\:/ + end + end + end + + describe 'on a commit' do + let(:commit) { project.commit } + let(:note) { create(:diff_note_on_commit) } + + subject { Notify.note_commit_email(recipient.id, note.id) } + + it_behaves_like 'a note email on a diff', :diff_note_on_commit + it_behaves_like 'it should show Gmail Actions View Commit link' + it_behaves_like 'a user cannot unsubscribe through footer link' + end + + describe 'on a merge request' do + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:note) { create(:diff_note_on_merge_request) } + + subject { Notify.note_merge_request_email(recipient.id, note.id) } + + it_behaves_like 'a note email on a diff', :diff_note_on_merge_request + it_behaves_like 'it should show Gmail Actions View Merge request link' + it_behaves_like 'an unsubscribeable thread' + end + end end context 'for a group' do @@ -1099,4 +1172,38 @@ describe Notify do is_expected.to have_body_text /#{diff_path}/ end end + + describe 'HTML emails setting' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:multipart_mail) { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") } + + context 'when disabled' do + it 'only sends the text template' do + stub_application_setting(html_emails_enabled: false) + + EmailTemplateInterceptor.delivering_email(multipart_mail) + + expect(multipart_mail).to have_part_with('text/plain') + expect(multipart_mail).not_to have_part_with('text/html') + end + end + + context 'when enabled' do + it 'sends a multipart message' do + stub_application_setting(html_emails_enabled: true) + + EmailTemplateInterceptor.delivering_email(multipart_mail) + + expect(multipart_mail).to have_part_with('text/plain') + expect(multipart_mail).to have_part_with('text/html') + end + end + + matcher :have_part_with do |expected| + match do |actual| + actual.body.parts.any? { |part| part.content_type.try(:match, %r(#{expected})) } + end + end + end end diff --git a/spec/models/cycle_analytics/code_spec.rb b/spec/models/cycle_analytics/code_spec.rb index 7691d690db0..7771785ead3 100644 --- a/spec/models/cycle_analytics/code_spec.rb +++ b/spec/models/cycle_analytics/code_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#code', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } context 'with deployment' do generate_cycle_analytics_spec( diff --git a/spec/models/cycle_analytics/issue_spec.rb b/spec/models/cycle_analytics/issue_spec.rb index f649b44d367..5ed3d37f2fb 100644 --- a/spec/models/cycle_analytics/issue_spec.rb +++ b/spec/models/cycle_analytics/issue_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#issue', models: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :issue, diff --git a/spec/models/cycle_analytics/plan_spec.rb b/spec/models/cycle_analytics/plan_spec.rb index 2cdefbeef21..baf3e3241a1 100644 --- a/spec/models/cycle_analytics/plan_spec.rb +++ b/spec/models/cycle_analytics/plan_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#plan', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :plan, diff --git a/spec/models/cycle_analytics/production_spec.rb b/spec/models/cycle_analytics/production_spec.rb index 1f5e5cab92d..21b9c6e7150 100644 --- a/spec/models/cycle_analytics/production_spec.rb +++ b/spec/models/cycle_analytics/production_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#production', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :production, diff --git a/spec/models/cycle_analytics/review_spec.rb b/spec/models/cycle_analytics/review_spec.rb index 0ed080a42b1..158621d59a4 100644 --- a/spec/models/cycle_analytics/review_spec.rb +++ b/spec/models/cycle_analytics/review_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#review', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :review, diff --git a/spec/models/cycle_analytics/staging_spec.rb b/spec/models/cycle_analytics/staging_spec.rb index af1c4477ddb..dad653964b7 100644 --- a/spec/models/cycle_analytics/staging_spec.rb +++ b/spec/models/cycle_analytics/staging_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#staging', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :staging, diff --git a/spec/models/cycle_analytics/summary_spec.rb b/spec/models/cycle_analytics/summary_spec.rb index 9d67bc82cba..725bc68b25f 100644 --- a/spec/models/cycle_analytics/summary_spec.rb +++ b/spec/models/cycle_analytics/summary_spec.rb @@ -4,7 +4,7 @@ describe CycleAnalytics::Summary, models: true do let(:project) { create(:project) } let(:from) { Time.now } let(:user) { create(:user, :admin) } - subject { described_class.new(project, from: from) } + subject { described_class.new(project, user, from: from) } describe "#new_issues" do it "finds the number of issues created after the 'from date'" do diff --git a/spec/models/cycle_analytics/test_spec.rb b/spec/models/cycle_analytics/test_spec.rb index 02ddfeed9c1..2313724e8f3 100644 --- a/spec/models/cycle_analytics/test_spec.rb +++ b/spec/models/cycle_analytics/test_spec.rb @@ -6,7 +6,7 @@ describe 'CycleAnalytics#test', feature: true do let(:project) { create(:project) } let(:from_date) { 10.days.ago } let(:user) { create(:user, :admin) } - subject { CycleAnalytics.new(project, from: from_date) } + subject { CycleAnalytics.new(project, user, from: from_date) } generate_cycle_analytics_spec( phase: :test, diff --git a/spec/models/discussion_spec.rb b/spec/models/discussion_spec.rb index 0142706d140..2a67c60b978 100644 --- a/spec/models/discussion_spec.rb +++ b/spec/models/discussion_spec.rb @@ -590,4 +590,23 @@ describe Discussion, model: true do end end end + + describe "#truncated_diff_lines" do + let(:truncated_lines) { subject.truncated_diff_lines } + + context "when diff is greater than allowed number of truncated diff lines " do + it "returns fewer lines" do + expect(subject.diff_lines.count).to be > described_class::NUMBER_OF_TRUNCATED_DIFF_LINES + + expect(truncated_lines.count).to be <= described_class::NUMBER_OF_TRUNCATED_DIFF_LINES + end + end + + context "when some diff lines are meta" do + it "returns no meta lines" do + expect(subject.diff_lines).to include(be_meta) + expect(truncated_lines).not_to include(be_meta) + end + end + end end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index b684053cd02..f8660da031d 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -260,6 +260,24 @@ describe Event, models: true do end end + describe '#authored_by?' do + let(:event) { build(:event) } + + it 'returns true when the event author and user are the same' do + expect(event.authored_by?(event.author)).to eq(true) + end + + it 'returns false when passing nil as an argument' do + expect(event.authored_by?(nil)).to eq(false) + end + + it 'returns false when the given user is not the author of the event' do + user = double(:user, id: -1) + + expect(event.authored_by?(user)).to eq(false) + end + end + def create_event(project, user, attrs = {}) data = { before: Gitlab::Git::BLANK_SHA, diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 19baf238b8d..30cc91bf265 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -570,7 +570,7 @@ describe MergeRequest, models: true do end end - describe '#pipeline' do + describe '#head_pipeline' do describe 'when the source project exists' do it 'returns the latest pipeline' do pipeline = double(:ci_pipeline, ref: 'master') @@ -581,7 +581,7 @@ describe MergeRequest, models: true do with('master', '123abc'). and_return(pipeline) - expect(subject.pipeline).to eq(pipeline) + expect(subject.head_pipeline).to eq(pipeline) end end @@ -589,7 +589,7 @@ describe MergeRequest, models: true do it 'returns nil' do allow(subject).to receive(:source_project).and_return(nil) - expect(subject.pipeline).to be_nil + expect(subject.head_pipeline).to be_nil end end end @@ -857,7 +857,7 @@ describe MergeRequest, models: true do context 'and a failed pipeline is associated' do before do pipeline.update(status: 'failed') - allow(subject).to receive(:pipeline) { pipeline } + allow(subject).to receive(:head_pipeline) { pipeline } end it { expect(subject.mergeable_ci_state?).to be_falsey } @@ -866,7 +866,7 @@ describe MergeRequest, models: true do context 'and a successful pipeline is associated' do before do pipeline.update(status: 'success') - allow(subject).to receive(:pipeline) { pipeline } + allow(subject).to receive(:head_pipeline) { pipeline } end it { expect(subject.mergeable_ci_state?).to be_truthy } @@ -875,7 +875,7 @@ describe MergeRequest, models: true do context 'and a skipped pipeline is associated' do before do pipeline.update(status: 'skipped') - allow(subject).to receive(:pipeline) { pipeline } + allow(subject).to receive(:head_pipeline) { pipeline } end it { expect(subject.mergeable_ci_state?).to be_truthy } @@ -883,7 +883,7 @@ describe MergeRequest, models: true do context 'when no pipeline is associated' do before do - allow(subject).to receive(:pipeline) { nil } + allow(subject).to receive(:head_pipeline) { nil } end it { expect(subject.mergeable_ci_state?).to be_truthy } @@ -896,7 +896,7 @@ describe MergeRequest, models: true do context 'and a failed pipeline is associated' do before do pipeline.statuses << create(:commit_status, status: 'failed', project: project) - allow(subject).to receive(:pipeline) { pipeline } + allow(subject).to receive(:head_pipeline) { pipeline } end it { expect(subject.mergeable_ci_state?).to be_truthy } @@ -904,7 +904,7 @@ describe MergeRequest, models: true do context 'when no pipeline is associated' do before do - allow(subject).to receive(:pipeline) { nil } + allow(subject).to receive(:head_pipeline) { nil } end it { expect(subject.mergeable_ci_state?).to be_truthy } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index da38254d1bc..8abcce42ce0 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -361,10 +361,15 @@ describe Project, models: true do describe '#get_issue' do let(:project) { create(:empty_project) } let!(:issue) { create(:issue, project: project) } + let(:user) { create(:user) } + + before do + project.team << [user, :developer] + end context 'with default issues tracker' do it 'returns an issue' do - expect(project.get_issue(issue.iid)).to eq issue + expect(project.get_issue(issue.iid, user)).to eq issue end it 'returns count of open issues' do @@ -372,7 +377,12 @@ describe Project, models: true do end it 'returns nil when no issue found' do - expect(project.get_issue(999)).to be_nil + expect(project.get_issue(999, user)).to be_nil + end + + it "returns nil when user doesn't have access" do + user = create(:user) + expect(project.get_issue(issue.iid, user)).to eq nil end end @@ -382,7 +392,7 @@ describe Project, models: true do end it 'returns an ExternalIssue' do - issue = project.get_issue('FOO-1234') + issue = project.get_issue('FOO-1234', user) expect(issue).to be_kind_of(ExternalIssue) expect(issue.iid).to eq 'FOO-1234' expect(issue.project).to eq project diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 04afb8ebc98..b797d19161d 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1303,32 +1303,36 @@ describe Repository, models: true do repository.add_tag(user, '8.5', 'master', 'foo') end - it 'does not create a tag when a pre-hook fails' do - allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([false, '']) - - expect do - repository.add_tag(user, '8.5', 'master', 'foo') - end.to raise_error(GitHooksService::PreReceiveError) + it 'returns a Gitlab::Git::Tag object' do + tag = repository.add_tag(user, '8.5', 'master', 'foo') - repository.expire_tags_cache - expect(repository.find_tag('8.5')).to be_nil + expect(tag).to be_a(Gitlab::Git::Tag) end - it 'passes tag SHA to hooks' do - spy = GitHooksService.new - allow(GitHooksService).to receive(:new).and_return(spy) - allow(spy).to receive(:execute).and_call_original + it 'passes commit SHA to pre-receive and update hooks,\ + and tag SHA to post-receive hook' do + pre_receive_hook = Gitlab::Git::Hook.new('pre-receive', repository.path_to_repo) + update_hook = Gitlab::Git::Hook.new('update', repository.path_to_repo) + post_receive_hook = Gitlab::Git::Hook.new('post-receive', repository.path_to_repo) - tag = repository.add_tag(user, '8.5', 'master', 'foo') + allow(Gitlab::Git::Hook).to receive(:new). + and_return(pre_receive_hook, update_hook, post_receive_hook) - expect(spy).to have_received(:execute). - with(anything, anything, anything, tag.target, anything) - end + allow(pre_receive_hook).to receive(:trigger).and_call_original + allow(update_hook).to receive(:trigger).and_call_original + allow(post_receive_hook).to receive(:trigger).and_call_original - it 'returns a Gitlab::Git::Tag object' do tag = repository.add_tag(user, '8.5', 'master', 'foo') - expect(tag).to be_a(Gitlab::Git::Tag) + commit_sha = repository.commit('master').id + tag_sha = tag.target + + expect(pre_receive_hook).to have_received(:trigger). + with(anything, anything, commit_sha, anything) + expect(update_hook).to have_received(:trigger). + with(anything, anything, commit_sha, anything) + expect(post_receive_hook).to have_received(:trigger). + with(anything, anything, tag_sha, anything) end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 91826e5884d..14c891994d0 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1349,4 +1349,31 @@ describe User, models: true do expect(projects).to be_empty end end + + describe '#refresh_authorized_projects', redis: true do + let(:project1) { create(:empty_project) } + let(:project2) { create(:empty_project) } + let(:user) { create(:user) } + + before do + project1.team << [user, :reporter] + project2.team << [user, :guest] + + user.project_authorizations.delete_all + user.refresh_authorized_projects + end + + it 'refreshes the list of authorized projects' do + expect(user.project_authorizations.count).to eq(2) + end + + it 'sets the authorized_projects_populated column' do + expect(user.authorized_projects_populated).to eq(true) + end + + it 'stores the correct access levels' do + expect(user.project_authorizations.where(access_level: Gitlab::Access::GUEST).exists?).to eq(true) + expect(user.project_authorizations.where(access_level: Gitlab::Access::REPORTER).exists?).to eq(true) + end + end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 7bae055b241..ae7994af981 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -365,6 +365,24 @@ describe API::API, api: true do let(:base_url) { "/projects/#{project.id}" } let(:title) { milestone.title } + it "returns 404 on private projects for other users" do + private_project = create(:empty_project, :private) + create(:issue, project: private_project) + + get api("/projects/#{private_project.id}/issues", non_member) + + expect(response).to have_http_status(404) + end + + it 'returns no issues when user has access to project but not issues' do + restricted_project = create(:empty_project, :public, issues_access_level: ProjectFeature::PRIVATE) + create(:issue, project: restricted_project) + + get api("/projects/#{restricted_project.id}/issues", non_member) + + expect(json_response).to eq([]) + end + it 'returns project issues without confidential issues for non project members' do get api("#{base_url}/issues", non_member) expect(response).to have_http_status(200) @@ -697,6 +715,14 @@ describe API::API, api: true do expect(Time.parse(json_response['created_at'])).to be_like_time(creation_time) end end + + context 'the user can only read the issue' do + it 'cannot create new labels' do + expect do + post api("/projects/#{project.id}/issues", non_member), title: 'new issue', labels: 'label, label2' + end.not_to change { project.labels.count } + end + end end describe 'POST /projects/:id/issues with spam filtering' do @@ -839,8 +865,8 @@ describe API::API, api: true do end it 'removes all labels' do - put api("/projects/#{project.id}/issues/#{issue.id}", user), - labels: '' + put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: '' + expect(response).to have_http_status(200) expect(json_response['labels']).to eq([]) end @@ -892,8 +918,8 @@ describe API::API, api: true do update_time = 2.weeks.ago put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: 'label3', state_event: 'close', updated_at: update_time - expect(response).to have_http_status(200) + expect(response).to have_http_status(200) expect(json_response['labels']).to include 'label3' expect(Time.parse(json_response['updated_at'])).to be_like_time(update_time) end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index b93577ef9d4..1e25ae60eef 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -402,14 +402,6 @@ describe API::API, api: true do end end - describe "PUT /projects/:id/merge_requests/:merge_request_id to close MR" do - it "returns merge_request" do - put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: "close" - expect(response).to have_http_status(200) - expect(json_response['state']).to eq('closed') - end - end - describe "PUT /projects/:id/merge_requests/:merge_request_id/merge" do let(:pipeline) { create(:ci_pipeline_without_jobs) } @@ -473,8 +465,9 @@ describe API::API, api: true do expect(response).to have_http_status(200) end + it "enables merge when pipeline succeeds if the pipeline is active" do - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_return(pipeline) + allow_any_instance_of(MergeRequest).to receive(:head_pipeline).and_return(pipeline) allow(pipeline).to receive(:active?).and_return(true) put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/merge", user), merge_when_build_succeeds: true @@ -486,6 +479,15 @@ describe API::API, api: true do end describe "PUT /projects/:id/merge_requests/:merge_request_id" do + context "to close a MR" do + it "returns merge_request" do + put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), state_event: "close" + + expect(response).to have_http_status(200) + expect(json_response['state']).to eq('closed') + end + end + it "updates title and returns merge_request" do put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), title: "New title" expect(response).to have_http_status(200) @@ -511,10 +513,10 @@ describe API::API, api: true do end it 'allows special label names' do - put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", - user), - title: 'new issue', - labels: 'label, label?, label&foo, ?, &' + put api("/projects/#{project.id}/merge_requests/#{merge_request.id}", user), + title: 'new issue', + labels: 'label, label?, label&foo, ?, &' + expect(response.status).to eq(200) expect(json_response['labels']).to include 'label' expect(json_response['labels']).to include 'label?' @@ -543,7 +545,7 @@ describe API::API, api: true do it "returns 404 if note is attached to non existent merge request" do post api("/projects/#{project.id}/merge_requests/404/comments", user), - note: 'My comment' + note: 'My comment' expect(response).to have_http_status(404) end end diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb index d83f7883c78..a7e511aaeda 100644 --- a/spec/requests/api/pipelines_spec.rb +++ b/spec/requests/api/pipelines_spec.rb @@ -103,6 +103,18 @@ describe API::API, api: true do expect(json_response['message']).to eq '404 Not found' expect(json_response['id']).to be nil end + + context 'with coverage' do + before do + create(:ci_build, coverage: 30, pipeline: pipeline) + end + + it 'exposes the coverage' do + get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user) + + expect(json_response["coverage"].to_i).to eq(30) + end + end end context 'unauthorized user' do diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index ce9c96ace21..bb0344e5995 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -128,7 +128,7 @@ describe API::API, api: true do ) end - it 'retusn status 200' do + it 'returns status 200' do post api("/projects/#{project.id}/services/mattermost_slash_commands/trigger"), params expect(response).to have_http_status(200) diff --git a/spec/requests/projects/cycle_analytics_events_spec.rb b/spec/requests/projects/cycle_analytics_events_spec.rb index 705dbb7d1c0..5c90fd9bad9 100644 --- a/spec/requests/projects/cycle_analytics_events_spec.rb +++ b/spec/requests/projects/cycle_analytics_events_spec.rb @@ -40,7 +40,7 @@ describe 'cycle analytics events' do expect(json_response['events']).not_to be_empty - first_mr_iid = MergeRequest.order(created_at: :desc).pluck(:iid).first.to_s + first_mr_iid = project.merge_requests.order(id: :desc).pluck(:iid).first.to_s expect(json_response['events'].first['iid']).to eq(first_mr_iid) end diff --git a/spec/serializers/analytics_build_entity_spec.rb b/spec/serializers/analytics_build_entity_spec.rb index c0b7e86b17c..6b33fe66a63 100644 --- a/spec/serializers/analytics_build_entity_spec.rb +++ b/spec/serializers/analytics_build_entity_spec.rb @@ -7,7 +7,9 @@ describe AnalyticsBuildEntity do context 'build with an author' do let(:user) { create(:user) } - let(:build) { create(:ci_build, author: user, started_at: 2.hours.ago, finished_at: 1.hour.ago) } + let(:started_at) { 2.hours.ago } + let(:finished_at) { 1.hour.ago } + let(:build) { create(:ci_build, author: user, started_at: started_at, finished_at: finished_at) } subject { entity.as_json } @@ -31,5 +33,54 @@ describe AnalyticsBuildEntity do it 'contains the duration' do expect(subject[:total_time]).to eq(hours: 1 ) end + + context 'no started at or finished at date' do + let(:started_at) { nil } + let(:finished_at) { nil } + + it 'does not blow up' do + expect{ subject[:date] }.not_to raise_error + end + + it 'shows the right message' do + expect(subject[:date]).to eq('Not started') + end + + it 'shows the right total time' do + expect(subject[:total_time]).to eq({}) + end + end + + context 'no started at date' do + let(:started_at) { nil } + + it 'does not blow up' do + expect{ subject[:date] }.not_to raise_error + end + + it 'shows the right message' do + expect(subject[:date]).to eq('Not started') + end + + it 'shows the right total time' do + expect(subject[:total_time]).to eq({}) + end + end + + context 'no finished at date' do + let(:finished_at) { nil } + + it 'does not blow up' do + expect{ subject[:date] }.not_to raise_error + end + + it 'shows the right message' do + expect(subject[:date]).to eq('about 2 hours ago') + end + + it 'shows the right total time' do + expect(subject[:total_time]).to eq({ hours: 2 }) + end + end end end diff --git a/spec/serializers/build_entity_spec.rb b/spec/serializers/build_entity_spec.rb index 6dcfaec259e..60c9642ee2c 100644 --- a/spec/serializers/build_entity_spec.rb +++ b/spec/serializers/build_entity_spec.rb @@ -1,23 +1,30 @@ require 'spec_helper' describe BuildEntity do + let(:build) { create(:ci_build) } + let(:entity) do described_class.new(build, request: double) end subject { entity.as_json } - context 'when build is a regular job' do - let(:build) { create(:ci_build) } + it 'contains paths to build page and retry action' do + expect(subject).to include(:build_path, :retry_path) + end - it 'contains paths to build page and retry action' do - expect(subject).to include(:build_path, :retry_path) - expect(subject).not_to include(:play_path) - end + it 'does not contain sensitive information' do + expect(subject).not_to include(/token/) + expect(subject).not_to include(/variables/) + end + + it 'contains timestamps' do + expect(subject).to include(:created_at, :updated_at) + end - it 'does not contain sensitive information' do - expect(subject).not_to include(/token/) - expect(subject).not_to include(/variables/) + context 'when build is a regular job' do + it 'does not contain path to play action' do + expect(subject).not_to include(:play_path) end end diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index ff113efd916..ebb11166964 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -1,31 +1,10 @@ require 'spec_helper' describe Ci::ProcessPipelineService, services: true do - let(:pipeline) { create(:ci_pipeline, ref: 'master') } + let(:pipeline) { create(:ci_empty_pipeline, ref: 'master') } let(:user) { create(:user) } - let(:config) { nil } - - before do - allow(pipeline).to receive(:ci_yaml_file).and_return(config) - end describe '#execute' do - def all_builds - pipeline.builds - end - - def builds - all_builds.where.not(status: [:created, :skipped]) - end - - def process_pipeline - described_class.new(pipeline.project, user).execute(pipeline) - end - - def succeed_pending - builds.pending.update_all(status: 'success') - end - context 'start queuing next builds' do before do create(:ci_build, :created, pipeline: pipeline, name: 'linux', stage_idx: 0) @@ -223,10 +202,6 @@ describe Ci::ProcessPipelineService, services: true do pipeline.builds.running_or_pending.each(&:success) expect(manual_actions).to be_many # production and clear cache end - - def manual_actions - pipeline.manual_actions - end end end @@ -282,15 +257,6 @@ describe Ci::ProcessPipelineService, services: true do expect(builds.map(&:status)).to eq(%w[success skipped pending]) end end - - def create_build(name, stage_idx, when_value = nil) - create(:ci_build, - :created, - pipeline: pipeline, - name: name, - stage_idx: stage_idx, - when: when_value) - end end context 'when failed build in the middle stage is retried' do @@ -327,65 +293,92 @@ describe Ci::ProcessPipelineService, services: true do end end - context 'creates a builds from .gitlab-ci.yml' do - let(:config) do - YAML.dump({ - rspec: { - stage: 'test', - script: 'rspec' - }, - rubocop: { - stage: 'test', - script: 'rubocop' - }, - deploy: { - stage: 'deploy', - script: 'deploy' - } - }) + context 'when there are builds that are not created yet' do + let(:pipeline) do + create(:ci_pipeline, config: config) end - # Using stubbed .gitlab-ci.yml created in commit factory - # + let(:config) do + { rspec: { stage: 'test', script: 'rspec' }, + deploy: { stage: 'deploy', script: 'rsync' } } + end before do - stub_ci_pipeline_yaml_file(config) create(:ci_build, :created, pipeline: pipeline, name: 'linux', stage: 'build', stage_idx: 0) create(:ci_build, :created, pipeline: pipeline, name: 'mac', stage: 'build', stage_idx: 0) end - it 'when processing a pipeline' do - # Currently we have two builds with state created + it 'processes the pipeline' do + # Currently we have five builds with state created + # expect(builds.count).to eq(0) expect(all_builds.count).to eq(2) - # Create builds will mark the created as pending - expect(process_pipeline).to be_truthy + # Process builds service will enqueue builds from the first stage. + # + process_pipeline + expect(builds.count).to eq(2) expect(all_builds.count).to eq(2) - # When we builds succeed we will create a rest of pipeline from .gitlab-ci.yml - # We will have 2 succeeded, 2 pending (from stage test), total 5 (one more build from deploy) + # When builds succeed we will enqueue remaining builds. + # + # We will have 2 succeeded, 1 pending (from stage test), total 4 (two + # additional build from `.gitlab-ci.yml`). + # succeed_pending - expect(process_pipeline).to be_truthy + process_pipeline + expect(builds.success.count).to eq(2) - expect(builds.pending.count).to eq(2) - expect(all_builds.count).to eq(5) + expect(builds.pending.count).to eq(1) + expect(all_builds.count).to eq(4) - # When we succeed the 2 pending from stage test, - # We will queue a deploy stage, no new builds will be created + # When pending build succeeds in stage test, we enqueue deploy stage. + # succeed_pending - expect(process_pipeline).to be_truthy + process_pipeline + expect(builds.pending.count).to eq(1) - expect(builds.success.count).to eq(4) - expect(all_builds.count).to eq(5) + expect(builds.success.count).to eq(3) + expect(all_builds.count).to eq(4) - # When we succeed last pending build, we will have a total of 5 succeeded builds, no new builds will be created + # When the last one succeeds we have 4 successful builds. + # succeed_pending - expect(process_pipeline).to be_falsey - expect(builds.success.count).to eq(5) - expect(all_builds.count).to eq(5) + process_pipeline + + expect(builds.success.count).to eq(4) + expect(all_builds.count).to eq(4) end end end + + def all_builds + pipeline.builds + end + + def builds + all_builds.where.not(status: [:created, :skipped]) + end + + def process_pipeline + described_class.new(pipeline.project, user).execute(pipeline) + end + + def succeed_pending + builds.pending.update_all(status: 'success') + end + + def manual_actions + pipeline.manual_actions + end + + def create_build(name, stage_idx, when_value = nil) + create(:ci_build, + :created, + pipeline: pipeline, + name: name, + stage_idx: stage_idx, + when: when_value) + end end diff --git a/spec/services/labels/transfer_service_spec.rb b/spec/services/labels/transfer_service_spec.rb index ddf3527dc0f..13654a0881c 100644 --- a/spec/services/labels/transfer_service_spec.rb +++ b/spec/services/labels/transfer_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Labels::TransferService, services: true do describe '#execute' do - let(:user) { create(:user) } + let(:user) { create(:admin) } let(:group_1) { create(:group) } let(:group_2) { create(:group) } let(:group_3) { create(:group) } diff --git a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb index a44312dd363..bb7830c7eea 100644 --- a/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb +++ b/spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb @@ -20,13 +20,19 @@ describe MergeRequests::AddTodoWhenBuildFailsService do let(:todo_service) { TodoService.new } let(:merge_request) do - create(:merge_request, merge_user: user, source_branch: 'master', - target_branch: 'feature', source_project: project, target_project: project, + create(:merge_request, merge_user: user, + source_branch: 'master', + target_branch: 'feature', + source_project: project, + target_project: project, state: 'opened') end before do - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_return(pipeline) + allow_any_instance_of(MergeRequest) + .to receive(:head_pipeline) + .and_return(pipeline) + allow(service).to receive(:todo_service).and_return(todo_service) end diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb index 3f5df049ea2..dc945ca4868 100644 --- a/spec/services/merge_requests/build_service_spec.rb +++ b/spec/services/merge_requests/build_service_spec.rb @@ -24,6 +24,8 @@ describe MergeRequests::BuildService, services: true do end before do + project.team << [user, :guest] + allow(CompareService).to receive_message_chain(:new, :execute).and_return(compare) allow(project).to receive(:commit).and_return(commit_1) allow(project).to receive(:commit).and_return(commit_2) @@ -168,6 +170,16 @@ describe MergeRequests::BuildService, services: true do expect(merge_request.title).to eq("Resolve \"#{issue.title}\"") end + context 'when issue is not accessible to user' do + before do + project.team.truncate + end + + it 'uses branch title as the merge request title' do + expect(merge_request.title).to eq("#{issue.iid} fix issue") + end + end + context 'issue does not exist' do let(:source_branch) { "#{issue.iid.succ}-fix-issue" } diff --git a/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb b/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb index 807f89e80b7..05cdbe5287a 100644 --- a/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb +++ b/spec/services/merge_requests/merge_request_diff_cache_service_spec.rb @@ -10,6 +10,7 @@ describe MergeRequests::MergeRequestDiffCacheService do expect(Rails.cache).to receive(:read).with(cache_key).and_return({}) expect(Rails.cache).to receive(:write).with(cache_key, anything) + allow_any_instance_of(Gitlab::Diff::File).to receive(:blob).and_return(double("text?" => true)) subject.execute(merge_request) end diff --git a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb index b3aa63817c7..f92978a33a3 100644 --- a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb +++ b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb @@ -27,7 +27,10 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do context 'first time enabling' do before do - allow(merge_request).to receive(:pipeline).and_return(pipeline) + allow(merge_request) + .to receive(:head_pipeline) + .and_return(pipeline) + service.execute(merge_request) end @@ -49,8 +52,12 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do let(:build) { create(:ci_build, ref: mr_merge_if_green_enabled.source_branch) } before do - allow(mr_merge_if_green_enabled).to receive(:pipeline).and_return(pipeline) - allow(mr_merge_if_green_enabled).to receive(:mergeable?).and_return(true) + allow(mr_merge_if_green_enabled).to receive(:head_pipeline) + .and_return(pipeline) + + allow(mr_merge_if_green_enabled).to receive(:mergeable?) + .and_return(true) + allow(pipeline).to receive(:success?).and_return(true) end @@ -144,9 +151,12 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do before do # This behavior of MergeRequest: we instantiate a new object - allow_any_instance_of(MergeRequest).to receive(:pipeline).and_wrap_original do - Ci::Pipeline.find(pipeline.id) - end + # + allow_any_instance_of(MergeRequest) + .to receive(:head_pipeline) + .and_wrap_original do + Ci::Pipeline.find(pipeline.id) + end end it "doesn't merge if any of stages failed" do diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb index e1f90e17cce..16d5f2bf0b8 100644 --- a/spec/support/capybara.rb +++ b/spec/support/capybara.rb @@ -7,7 +7,15 @@ timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 90 : 10 Capybara.javascript_driver = :poltergeist Capybara.register_driver :poltergeist do |app| - Capybara::Poltergeist::Driver.new(app, js_errors: true, timeout: timeout, window_size: [1366, 768]) + Capybara::Poltergeist::Driver.new( + app, + js_errors: true, + timeout: timeout, + window_size: [1366, 768], + phantomjs_options: [ + '--load-images=no' + ] + ) end Capybara.default_max_wait_time = timeout diff --git a/spec/support/javascript_fixtures_helpers.rb b/spec/support/javascript_fixtures_helpers.rb index adc3f48b434..99e98eebdb4 100644 --- a/spec/support/javascript_fixtures_helpers.rb +++ b/spec/support/javascript_fixtures_helpers.rb @@ -1,3 +1,4 @@ +require 'action_dispatch/testing/test_request' require 'fileutils' require 'gitlab/popen' @@ -30,13 +31,17 @@ module JavaScriptFixturesHelpers if response_mime_type.html? doc = Nokogiri::HTML::DocumentFragment.parse(fixture) + link_tags = doc.css('link') + link_tags.remove + scripts = doc.css('script') scripts.remove fixture = doc.to_html # replace relative links - fixture.gsub!(%r{="/}, '="https://fixture.invalid/') + test_host = ActionDispatch::TestRequest::DEFAULT_ENV['HTTP_HOST'] + fixture.gsub!(%r{="/}, "=\"http://#{test_host}/") end FileUtils.mkdir_p(File.dirname(fixture_file_name)) diff --git a/spec/support/matchers/access_matchers.rb b/spec/support/matchers/access_matchers.rb index 0497e391860..691d7e05f57 100644 --- a/spec/support/matchers/access_matchers.rb +++ b/spec/support/matchers/access_matchers.rb @@ -7,7 +7,7 @@ module AccessMatchers extend RSpec::Matchers::DSL include Warden::Test::Helpers - def emulate_user(user) + def emulate_user(user, project = nil) case user when :user login_as(create(:user)) @@ -19,6 +19,18 @@ module AccessMatchers login_as(create(:user, external: true)) when User login_as(user) + when :owner + raise ArgumentError, "cannot emulate owner without project" unless project + + login_as(project.owner) + when *Gitlab::Access.sym_options.keys + raise ArgumentError, "cannot emulate user #{user} without project" unless project + + role = user + user = create(:user) + project.public_send(:"add_#{role}", user) + + login_as(user) else raise ArgumentError, "cannot emulate user #{user}" end @@ -26,8 +38,7 @@ module AccessMatchers def description_for(user, type) if user.kind_of?(User) - # User#inspect displays too much information for RSpec's description - # messages + # User#inspect displays too much information for RSpec's descriptions "be #{type} for the specified user" else "be #{type} for #{user}" @@ -36,21 +47,31 @@ module AccessMatchers matcher :be_allowed_for do |user| match do |url| - emulate_user(user) - visit url + emulate_user(user, @project) + visit(url) + status_code != 404 && current_path != new_user_session_path end + chain :of do |project| + @project = project + end + description { description_for(user, 'allowed') } end matcher :be_denied_for do |user| match do |url| - emulate_user(user) - visit url + emulate_user(user, @project) + visit(url) + status_code == 404 || current_path == new_user_session_path end + chain :of do |project| + @project = project + end + description { description_for(user, 'denied') } end end diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb index 3fddfb3b62f..8020faa1f9c 100644 --- a/spec/views/layouts/_head.html.haml_spec.rb +++ b/spec/views/layouts/_head.html.haml_spec.rb @@ -1,10 +1,6 @@ require 'spec_helper' describe 'layouts/_head' do - before do - stub_template 'layouts/_user_styles.html.haml' => '' - end - it 'escapes HTML-safe strings in page_title' do stub_helper_with_safe_string(:page_title) diff --git a/spec/views/projects/merge_requests/_new_submit.html.haml_spec.rb b/spec/views/projects/merge_requests/_new_submit.html.haml_spec.rb new file mode 100644 index 00000000000..4f698a34ab5 --- /dev/null +++ b/spec/views/projects/merge_requests/_new_submit.html.haml_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe 'projects/merge_requests/_new_submit.html.haml', :view do + let(:merge_request) { create(:merge_request) } + let!(:pipeline) { create(:ci_empty_pipeline) } + + before do + controller.prepend_view_path('app/views/projects') + + assign(:merge_request, merge_request) + assign(:commits, merge_request.commits) + assign(:project, merge_request.target_project) + + allow(view).to receive(:can?).and_return(true) + allow(view).to receive(:url_for).and_return('#') + allow(view).to receive(:current_user).and_return(merge_request.author) + end + + context 'when there are pipelines for merge request but no pipeline for last commit' do + before do + assign(:pipelines, Ci::Pipeline.all) + assign(:pipeline, nil) + end + + it 'shows <<Pipelines>> tab and hides <<Builds>> tab' do + render + expect(rendered).to have_text('Pipelines 1') + expect(rendered).not_to have_text('Builds') + end + end +end diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb index 18a1aab766c..95e2458da35 100644 --- a/spec/workers/authorized_projects_worker_spec.rb +++ b/spec/workers/authorized_projects_worker_spec.rb @@ -1,22 +1,33 @@ require 'spec_helper' describe AuthorizedProjectsWorker do + let(:worker) { described_class.new } + describe '#perform' do it "refreshes user's authorized projects" do user = create(:user) - expect(User).to receive(:find_by).with(id: user.id).and_return(user) - expect(user).to receive(:refresh_authorized_projects) + expect(worker).to receive(:refresh).with(an_instance_of(User)) - described_class.new.perform(user.id) + worker.perform(user.id) end - context "when user is not found" do + context "when the user is not found" do it "does nothing" do - expect_any_instance_of(User).not_to receive(:refresh_authorized_projects) + expect(worker).not_to receive(:refresh) - described_class.new.perform(999_999) + described_class.new.perform(-1) end end end + + describe '#refresh', redis: true do + it 'refreshes the authorized projects of the user' do + user = create(:user) + + expect(user).to receive(:refresh_authorized_projects) + + worker.refresh(user) + end + end end |