diff options
author | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-03-29 16:14:59 +0200 |
---|---|---|
committer | Zeger-Jan van de Weg <zegerjan@gitlab.com> | 2016-03-29 16:14:59 +0200 |
commit | b231742687cf08d8663ce34a11f1b64f1fbe4a6a (patch) | |
tree | e7cbf5b49f65b2e53e5b7e38fbb1aee2f8f80b52 /spec | |
parent | aabe93ce9c2c4947595f6d29628d5e1030bfb372 (diff) | |
parent | 54957d6932c2b159e01b60ee1d4e191cfdf5b713 (diff) | |
download | gitlab-ce-b231742687cf08d8663ce34a11f1b64f1fbe4a6a.tar.gz |
Merge branch 'master' into add-ability-to-archive-a-project-via-api-14296add-ability-to-archive-a-project-via-api-14296
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/ci/projects_controller_spec.rb | 21 | ||||
-rw-r--r-- | spec/controllers/projects/snippets_controller_spec.rb | 107 | ||||
-rw-r--r-- | spec/controllers/root_controller_spec.rb | 22 | ||||
-rw-r--r-- | spec/features/issues/filter_by_milestone_spec.rb | 2 | ||||
-rw-r--r-- | spec/features/issues_spec.rb | 77 | ||||
-rw-r--r-- | spec/features/security/project/snippet/internal_access_spec.rb | 78 | ||||
-rw-r--r-- | spec/features/security/project/snippet/private_access_spec.rb | 63 | ||||
-rw-r--r-- | spec/features/security/project/snippet/public_access_spec.rb | 93 | ||||
-rw-r--r-- | spec/helpers/preferences_helper_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 6 | ||||
-rw-r--r-- | spec/models/repository_spec.rb | 27 | ||||
-rw-r--r-- | spec/requests/api/issues_spec.rb | 11 |
12 files changed, 457 insertions, 54 deletions
diff --git a/spec/controllers/ci/projects_controller_spec.rb b/spec/controllers/ci/projects_controller_spec.rb index db0748f323f..5022a3e2c80 100644 --- a/spec/controllers/ci/projects_controller_spec.rb +++ b/spec/controllers/ci/projects_controller_spec.rb @@ -5,6 +5,27 @@ describe Ci::ProjectsController do let!(:project) { create(:project, visibility, ci_id: 1) } let(:ci_id) { project.ci_id } + describe '#index' do + context 'user signed in' do + before do + sign_in(create(:user)) + get(:index) + end + + it 'redirects to /' do + expect(response).to redirect_to(root_path) + end + end + + context 'user not signed in' do + before { get(:index) } + + it 'redirects to sign in page' do + expect(response).to redirect_to(new_user_session_path) + end + end + end + ## # Specs for *deprecated* CI badge # diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb new file mode 100644 index 00000000000..0f32a30f18b --- /dev/null +++ b/spec/controllers/projects/snippets_controller_spec.rb @@ -0,0 +1,107 @@ +require 'spec_helper' + +describe Projects::SnippetsController do + let(:project) { create(:project_empty_repo, :public, snippets_enabled: true) } + let(:user) { create(:user) } + let(:user2) { create(:user) } + + before do + project.team << [user, :master] + project.team << [user2, :master] + end + + describe 'GET #index' do + context 'when the project snippet is private' do + let!(:project_snippet) { create(:project_snippet, :private, project: project, author: user) } + + context 'when anonymous' do + it 'does not include the private snippet' do + get :index, namespace_id: project.namespace.path, project_id: project.path + + expect(assigns(:snippets)).not_to include(project_snippet) + expect(response.status).to eq(200) + end + end + + context 'when signed in as the author' do + before { sign_in(user) } + + it 'renders the snippet' do + get :index, namespace_id: project.namespace.path, project_id: project.path + + expect(assigns(:snippets)).to include(project_snippet) + expect(response.status).to eq(200) + end + end + + context 'when signed in as a project member' do + before { sign_in(user2) } + + it 'renders the snippet' do + get :index, namespace_id: project.namespace.path, project_id: project.path + + expect(assigns(:snippets)).to include(project_snippet) + expect(response.status).to eq(200) + end + end + end + end + + %w[show raw].each do |action| + describe "GET ##{action}" do + context 'when the project snippet is private' do + let(:project_snippet) { create(:project_snippet, :private, project: project, author: user) } + + context 'when anonymous' do + it 'responds with status 404' do + get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param + + expect(response.status).to eq(404) + end + end + + context 'when signed in as the author' do + before { sign_in(user) } + + it 'renders the snippet' do + get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param + + expect(assigns(:snippet)).to eq(project_snippet) + expect(response.status).to eq(200) + end + end + + context 'when signed in as a project member' do + before { sign_in(user2) } + + it 'renders the snippet' do + get action, namespace_id: project.namespace.path, project_id: project.path, id: project_snippet.to_param + + expect(assigns(:snippet)).to eq(project_snippet) + expect(response.status).to eq(200) + end + end + end + + context 'when the project snippet does not exist' do + context 'when anonymous' do + it 'responds with status 404' do + get action, namespace_id: project.namespace.path, project_id: project.path, id: 42 + + expect(response.status).to eq(404) + end + end + + context 'when signed in' do + before { sign_in(user) } + + it 'responds with status 404' do + get action, namespace_id: project.namespace.path, project_id: project.path, id: 42 + + expect(response.status).to eq(404) + end + end + end + end + end +end diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb index 5a104ae7c99..b14d275f7fa 100644 --- a/spec/controllers/root_controller_spec.rb +++ b/spec/controllers/root_controller_spec.rb @@ -43,6 +43,28 @@ describe RootController do end end + context 'who has customized their dashboard setting for groups' do + before do + user.update_attribute(:dashboard, 'groups') + end + + it 'redirects to their group list' do + get :index + expect(response).to redirect_to dashboard_groups_path + end + end + + context 'who has customized their dashboard setting for todos' do + before do + user.update_attribute(:dashboard, 'todos') + end + + it 'redirects to their todo list' do + get :index + expect(response).to redirect_to dashboard_todos_path + end + end + context 'who uses the default dashboard setting' do it 'renders the default dashboard' do get :index diff --git a/spec/features/issues/filter_by_milestone_spec.rb b/spec/features/issues/filter_by_milestone_spec.rb index f6e33f651c4..d8e2ecb9feb 100644 --- a/spec/features/issues/filter_by_milestone_spec.rb +++ b/spec/features/issues/filter_by_milestone_spec.rb @@ -31,7 +31,7 @@ feature 'Issue filtering by Milestone', feature: true do def filter_by_milestone(title) find(".js-milestone-select").click sleep 0.5 - find(".milestone-filter a", text: title).click + find(".milestone-filter .dropdown-content a", text: title).click sleep 1 end end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index e844e681ebf..db46657c36a 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -34,20 +34,7 @@ describe 'Issues', feature: true do fill_in 'issue_title', with: 'bug 345' fill_in 'issue_description', with: 'bug description' end - - it 'does not change issue count' do - expect { click_button 'Save changes' }.to_not change { Issue.count } - end - - it 'should update issue fields' do - click_button 'Save changes' - - expect(page).to have_content @user.name - expect(page).to have_content 'bug 345' - expect(page).to have_content project.name - end end - end describe 'Editing issue assignee' do @@ -70,7 +57,7 @@ describe 'Issues', feature: true do click_button 'Save changes' page.within('.assignee') do - expect(page).to have_content 'None' + expect(page).to have_content 'No assignee - assign yourself' end expect(issue.reload.assignee).to be_nil @@ -198,20 +185,26 @@ describe 'Issues', feature: true do end describe 'update assignee from issue#show' do - let(:issue) { create(:issue, project: project, author: @user) } + let(:issue) { create(:issue, project: project, author: @user, assignee: @user) } context 'by autorized user' do - it 'with dropdown menu' do + it 'allows user to select unassigned', js: true do visit namespace_project_issue_path(project.namespace, project, issue) - find('.issuable-sidebar #issue_assignee_id'). - set project.team.members.first.id - click_button 'Update Issue' + page.within('.assignee') do + expect(page).to have_content "#{@user.name}" + end + + find('.block.assignee .edit-link').click + sleep 2 # wait for ajax stuff to complete + first('.dropdown-menu-user-link').click + sleep 2 + page.within('.assignee') do + expect(page).to have_content 'No assignee' + end - expect(page).to have_content 'Assignee' - has_select?('issue_assignee_id', - selected: project.team.members.first.name) + expect(issue.reload.assignee).to be_nil end end @@ -221,8 +214,6 @@ describe 'Issues', feature: true do before :each do project.team << [[guest], :guest] - issue.assignee = @user - issue.save end it 'shows assignee text', js: true do @@ -241,20 +232,23 @@ describe 'Issues', feature: true do context 'by authorized user' do - it 'with dropdown menu' do - visit namespace_project_issue_path(project.namespace, project, issue) - find('.issuable-sidebar'). - select(milestone.title, from: 'issue_milestone_id') - click_button 'Update Issue' + it 'allows user to select unassigned', js: true do + visit namespace_project_issue_path(project.namespace, project, issue) - expect(page).to have_content "Milestone changed to #{milestone.title}" + page.within('.milestone') do + expect(page).to have_content "None" + end + find('.block.milestone .edit-link').click + sleep 2 # wait for ajax stuff to complete + first('.dropdown-content li').click + sleep 2 page.within('.milestone') do - expect(page).to have_content milestone.title + expect(page).to have_content 'None' end - has_select?('issue_assignee_id', selected: milestone.title) + expect(issue.reload.milestone).to be_nil end end @@ -283,25 +277,6 @@ describe 'Issues', feature: true do issue.assignee = user2 issue.save end - - it 'allows user to remove assignee', js: true do - visit namespace_project_issue_path(project.namespace, project, issue) - - page.within('.assignee') do - expect(page).to have_content user2.name - end - - find('.assignee .edit-link').click - sleep 2 # wait for ajax stuff to complete - first('.user-result').click - - page.within('.assignee') do - expect(page).to have_content 'None' - end - - sleep 2 # wait for ajax stuff to complete - expect(issue.reload.assignee).to be_nil - end end end diff --git a/spec/features/security/project/snippet/internal_access_spec.rb b/spec/features/security/project/snippet/internal_access_spec.rb new file mode 100644 index 00000000000..db53a9cec97 --- /dev/null +++ b/spec/features/security/project/snippet/internal_access_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe "Internal Project Snippets Access", feature: true do + include AccessMatchers + + 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) } + let(:internal_snippet) { create(:project_snippet, :internal, project: project, author: owner) } + let(:private_snippet) { create(:project_snippet, :private, project: project, author: owner) } + + before do + project.team << [master, :master] + project.team << [developer, :developer] + project.team << [reporter, :reporter] + project.team << [guest, :guest] + 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 } + 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 } + end + + describe "GET /:project_path/snippets/:id for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + + 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 } + end + + describe "GET /:project_path/snippets/:id for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + 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 } + end +end diff --git a/spec/features/security/project/snippet/private_access_spec.rb b/spec/features/security/project/snippet/private_access_spec.rb new file mode 100644 index 00000000000..d23d645c8e5 --- /dev/null +++ b/spec/features/security/project/snippet/private_access_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe "Private Project Snippets Access", feature: true do + include AccessMatchers + + 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) } + let(:private_snippet) { create(:project_snippet, :private, project: project, author: owner) } + + before do + project.team << [master, :master] + project.team << [developer, :developer] + project.team << [reporter, :reporter] + project.team << [guest, :guest] + 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 } + 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 } + end + + describe "GET /:project_path/snippets/:id for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + 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 } + end +end diff --git a/spec/features/security/project/snippet/public_access_spec.rb b/spec/features/security/project/snippet/public_access_spec.rb new file mode 100644 index 00000000000..e3665b6116a --- /dev/null +++ b/spec/features/security/project/snippet/public_access_spec.rb @@ -0,0 +1,93 @@ +require 'spec_helper' + +describe "Public Project Snippets Access", feature: true do + include AccessMatchers + + 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) } + let(:public_snippet) { create(:project_snippet, :public, project: project, author: owner) } + let(:internal_snippet) { create(:project_snippet, :internal, project: project, author: owner) } + let(:private_snippet) { create(:project_snippet, :private, project: project, author: owner) } + + before do + project.team << [master, :master] + project.team << [developer, :developer] + project.team << [reporter, :reporter] + project.team << [guest, :guest] + 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 } + 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 } + end + + describe "GET /:project_path/snippets/:id for a public snippet" do + subject { namespace_project_snippet_path(project.namespace, project, public_snippet) } + + 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 } + end + + describe "GET /:project_path/snippets/:id for an internal snippet" do + subject { namespace_project_snippet_path(project.namespace, project, internal_snippet) } + + 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 } + end + + describe "GET /:project_path/snippets/:id for a private snippet" do + subject { namespace_project_snippet_path(project.namespace, project, private_snippet) } + + 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 } + end +end diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb index e5df59c4fba..2f9291afc3f 100644 --- a/spec/helpers/preferences_helper_spec.rb +++ b/spec/helpers/preferences_helper_spec.rb @@ -19,7 +19,9 @@ describe PreferencesHelper do ['Your Projects (default)', 'projects'], ['Starred Projects', 'stars'], ["Your Projects' Activity", 'project_activity'], - ["Starred Projects' Activity", 'starred_project_activity'] + ["Starred Projects' Activity", 'starred_project_activity'], + ["Your Groups", 'groups'], + ["Your Todos", 'todos'] ] end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 20f06f4b7e1..55f1c665b86 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -422,6 +422,12 @@ describe Project, models: true do it { should eq "http://localhost#{avatar_path}" } end + + context 'when git repo is empty' do + let(:project) { create(:empty_project) } + + it { should eq nil } + end end describe :ci_commit do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 7eac70ae948..f10d671104c 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2,6 +2,7 @@ require 'spec_helper' describe Repository, models: true do include RepoHelpers + TestBlob = Struct.new(:name) let(:repository) { create(:project).repository } let(:user) { create(:user) } @@ -131,7 +132,6 @@ describe Repository, models: true do describe "#license" do before do repository.send(:cache).expire(:license) - TestBlob = Struct.new(:name) end it 'test selection preference' do @@ -148,6 +148,25 @@ describe Repository, models: true do end end + describe "#gitlab_ci_yml" do + it 'returns valid file' do + files = [TestBlob.new('file'), TestBlob.new('.gitlab-ci.yml'), TestBlob.new('copying')] + expect(repository.tree).to receive(:blobs).and_return(files) + + expect(repository.gitlab_ci_yml.name).to eq('.gitlab-ci.yml') + end + + it 'returns nil if not exists' do + expect(repository.tree).to receive(:blobs).and_return([]) + expect(repository.gitlab_ci_yml).to be_nil + end + + it 'returns nil for empty repository' do + expect(repository).to receive(:empty?).and_return(true) + expect(repository.gitlab_ci_yml).to be_nil + end + end + describe :add_branch do context 'when pre hooks were successful' do it 'should run without errors' do @@ -725,6 +744,12 @@ describe Repository, models: true do end describe '#avatar' do + it 'returns nil if repo does not exist' do + expect(repository).to receive(:exists?).and_return(false) + + expect(repository.avatar).to eq(nil) + end + it 'returns the first avatar file found in the repository' do expect(repository).to receive(:blob_at_branch). with('master', 'logo.png'). diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index ce55cb7b0ae..822d3ad3017 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -318,6 +318,17 @@ describe API::API, api: true do 'is too long (maximum is 255 characters)' ]) end + + context 'when an admin or owner makes the request' do + it "accepts the creation date to be set" do + post api("/projects/#{project.id}/issues", user), + title: 'new issue', labels: 'label, label2', created_at: 2.weeks.ago + + expect(response.status).to eq(201) + # this take about a second, so probably not equal + expect(Time.parse(json_response['created_at'])).to be <= 2.weeks.ago + end + end end describe 'POST /projects/:id/issues with spam filtering' do |