diff options
Diffstat (limited to 'spec')
224 files changed, 9844 insertions, 4855 deletions
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index cc32805f5ec..186239d3096 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -7,26 +7,26 @@ describe ApplicationController do it 'should redirect if the user is over their password expiry' do user.password_expires_at = Time.new(2002) - user.ldap_user?.should be_false - controller.stub(:current_user).and_return(user) - controller.should_receive(:redirect_to) - controller.should_receive(:new_profile_password_path) + expect(user.ldap_user?).to be_falsey + allow(controller).to receive(:current_user).and_return(user) + expect(controller).to receive(:redirect_to) + expect(controller).to receive(:new_profile_password_path) controller.send(:check_password_expiration) end it 'should not redirect if the user is under their password expiry' do user.password_expires_at = Time.now + 20010101 - user.ldap_user?.should be_false - controller.stub(:current_user).and_return(user) - controller.should_not_receive(:redirect_to) + expect(user.ldap_user?).to be_falsey + allow(controller).to receive(:current_user).and_return(user) + expect(controller).not_to receive(:redirect_to) controller.send(:check_password_expiration) end it 'should not redirect if the user is over their password expiry but they are an ldap user' do user.password_expires_at = Time.new(2002) - user.stub(:ldap_user?).and_return(true) - controller.stub(:current_user).and_return(user) - controller.should_not_receive(:redirect_to) + allow(user).to receive(:ldap_user?).and_return(true) + allow(controller).to receive(:current_user).and_return(user) + expect(controller).not_to receive(:redirect_to) controller.send(:check_password_expiration) end end diff --git a/spec/controllers/blob_controller_spec.rb b/spec/controllers/blob_controller_spec.rb index 11d748ca77f..a1102f28340 100644 --- a/spec/controllers/blob_controller_spec.rb +++ b/spec/controllers/blob_controller_spec.rb @@ -9,29 +9,32 @@ describe Projects::BlobController do project.team << [user, :master] - project.stub(:branches).and_return(['master', 'foo/bar/baz']) - project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) + allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) + allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) controller.instance_variable_set(:@project, project) end describe "GET show" do render_views - before { get :show, project_id: project.to_param, id: id } + before do + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: id) + end context "valid branch, valid file" do let(:id) { 'master/README.md' } - it { should respond_with(:success) } + it { is_expected.to respond_with(:success) } end context "valid branch, invalid file" do let(:id) { 'master/invalid-path.rb' } - it { should respond_with(:not_found) } + it { is_expected.to respond_with(:not_found) } end context "invalid branch, valid file" do let(:id) { 'invalid-branch/README.md' } - it { should respond_with(:not_found) } + it { is_expected.to respond_with(:not_found) } end end @@ -39,13 +42,17 @@ describe Projects::BlobController do render_views before do - get :show, project_id: project.to_param, id: id + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: id) controller.instance_variable_set(:@blob, nil) end context 'redirect to tree' do let(:id) { 'markdown/doc' } - it { should redirect_to("/#{project.path_with_namespace}/tree/markdown/doc") } + it 'redirects' do + expect(subject). + to redirect_to("/#{project.path_with_namespace}/tree/markdown/doc") + end end end end diff --git a/spec/controllers/branches_controller_spec.rb b/spec/controllers/branches_controller_spec.rb new file mode 100644 index 00000000000..51397382cfb --- /dev/null +++ b/spec/controllers/branches_controller_spec.rb @@ -0,0 +1,58 @@ +require 'spec_helper' + +describe Projects::BranchesController do + let(:project) { create(:project) } + let(:user) { create(:user) } + + before do + sign_in(user) + + project.team << [user, :master] + + allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) + allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) + controller.instance_variable_set(:@project, project) + end + + describe "POST create" do + render_views + + before { + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + branch_name: branch, + ref: ref + } + + context "valid branch name, valid source" do + let(:branch) { "merge_branch" } + let(:ref) { "master" } + it 'redirects' do + expect(subject). + to redirect_to("/#{project.path_with_namespace}/tree/merge_branch") + end + end + + context "invalid branch name, valid ref" do + let(:branch) { "<script>alert('merge');</script>" } + let(:ref) { "master" } + it 'redirects' do + expect(subject). + to redirect_to("/#{project.path_with_namespace}/tree/alert('merge');") + end + end + + context "valid branch name, invalid ref" do + let(:branch) { "merge_branch" } + let(:ref) { "<script>alert('ref');</script>" } + it { is_expected.to render_template('new') } + end + + context "invalid branch name, invalid ref" do + let(:branch) { "<script>alert('merge');</script>" } + let(:ref) { "<script>alert('ref');</script>" } + it { is_expected.to render_template('new') } + end + end +end diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb index f5822157ea4..3394a1f863f 100644 --- a/spec/controllers/commit_controller_spec.rb +++ b/spec/controllers/commit_controller_spec.rb @@ -13,27 +13,32 @@ describe Projects::CommitController do describe "#show" do shared_examples "export as" do |format| it "should generally work" do - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response).to be_success end it "should generate it" do - Commit.any_instance.should_receive(:"to_#{format}") + expect_any_instance_of(Commit).to receive(:"to_#{format}") - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) end it "should render it" do - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response.body).to eq(commit.send(:"to_#{format}")) end it "should not escape Html" do - Commit.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ') + allow_any_instance_of(Commit).to receive(:"to_#{format}"). + and_return('HTML entities &<>" ') - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response.body).to_not include('&') expect(response.body).to_not include('>') @@ -47,7 +52,8 @@ describe Projects::CommitController do let(:format) { :diff } it "should really only be a git diff" do - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response.body).to start_with("diff --git") end @@ -58,16 +64,28 @@ describe Projects::CommitController do let(:format) { :patch } it "should really be a git email patch" do - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response.body).to start_with("From #{commit.id}") end it "should contain a git diff" do - get :show, project_id: project.to_param, id: commit.id, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id, format: format) expect(response.body).to match(/^diff --git/) end end end + + describe "#branches" do + it "contains branch and tags information" do + get(:branches, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: commit.id) + + expect(assigns(:branches)).to include("master", "feature_conflict") + expect(assigns(:tags)).to include("v1.1.0") + end + end end diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb index 0c19d755eb1..2184b35152e 100644 --- a/spec/controllers/commits_controller_spec.rb +++ b/spec/controllers/commits_controller_spec.rb @@ -12,9 +12,10 @@ describe Projects::CommitsController do describe "GET show" do context "as atom feed" do it "should render as atom" do - get :show, project_id: project.to_param, id: "master", format: "atom" - response.should be_success - response.content_type.should == 'application/atom+xml' + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: "master", format: "atom") + expect(response).to be_success + expect(response.content_type).to eq('application/atom+xml') end end end diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb new file mode 100644 index 00000000000..5dd4124061c --- /dev/null +++ b/spec/controllers/import/bitbucket_controller_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe Import::BitbucketController do + let(:user) { create(:user, bitbucket_access_token: 'asd123', bitbucket_access_token_secret: "sekret") } + + before do + sign_in(user) + controller.stub(:bitbucket_import_enabled?).and_return(true) + end + + describe "GET callback" do + before do + session[:oauth_request_token] = {} + end + + it "updates access token" do + token = "asdasd12345" + secret = "sekrettt" + access_token = double(token: token, secret: secret) + Gitlab::BitbucketImport::Client.any_instance.stub(:get_token).and_return(access_token) + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket") + + get :callback + + expect(user.reload.bitbucket_access_token).to eq(token) + expect(user.reload.bitbucket_access_token_secret).to eq(secret) + expect(controller).to redirect_to(status_import_bitbucket_url) + end + end + + describe "GET status" do + before do + @repo = OpenStruct.new(slug: 'vim', owner: 'asd') + end + + it "assigns variables" do + @project = create(:project, import_type: 'bitbucket', creator_id: user.id) + controller.stub_chain(:client, :projects).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([@repo]) + end + + it "does not show already added project" do + @project = create(:project, import_type: 'bitbucket', creator_id: user.id, import_source: 'asd/vim') + controller.stub_chain(:client, :projects).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([]) + end + end + + describe "POST create" do + before do + @repo = { + slug: 'vim', + owner: "john" + }.with_indifferent_access + end + + it "takes already existing namespace" do + namespace = create(:namespace, name: "john", owner: user) + expect(Gitlab::BitbucketImport::KeyAdder). + to receive(:new).with(@repo, user). + and_return(double(execute: true)) + expect(Gitlab::BitbucketImport::ProjectCreator). + to receive(:new).with(@repo, namespace, user). + and_return(double(execute: true)) + controller.stub_chain(:client, :project).and_return(@repo) + + post :create, format: :js + end + end +end diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb new file mode 100644 index 00000000000..5b967bfcc0c --- /dev/null +++ b/spec/controllers/import/github_controller_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe Import::GithubController do + let(:user) { create(:user, github_access_token: 'asd123') } + + before do + sign_in(user) + controller.stub(:github_import_enabled?).and_return(true) + end + + describe "GET callback" do + it "updates access token" do + token = "asdasd12345" + allow_any_instance_of(Gitlab::GithubImport::Client). + to receive(:get_token).and_return(token) + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: 'asd123', + app_secret: 'asd123', + name: 'github') + + get :callback + + expect(user.reload.github_access_token).to eq(token) + expect(controller).to redirect_to(status_import_github_url) + end + end + + describe "GET status" do + before do + @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim') + @org = OpenStruct.new(login: 'company') + @org_repo = OpenStruct.new(login: 'company', full_name: 'company/repo') + end + + it "assigns variables" do + @project = create(:project, import_type: 'github', creator_id: user.id) + controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :orgs).and_return([@org]) + controller.stub_chain(:client, :org_repos).with(@org.login).and_return([@org_repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([@repo, @org_repo]) + end + + it "does not show already added project" do + @project = create(:project, import_type: 'github', creator_id: user.id, import_source: 'asd/vim') + controller.stub_chain(:client, :repos).and_return([@repo]) + controller.stub_chain(:client, :orgs).and_return([]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([]) + end + end + + describe "POST create" do + before do + @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim', owner: OpenStruct.new(login: "john")) + end + + it "takes already existing namespace" do + namespace = create(:namespace, name: "john", owner: user) + expect(Gitlab::GithubImport::ProjectCreator). + to receive(:new).with(@repo, namespace, user). + and_return(double(execute: true)) + controller.stub_chain(:client, :repo).and_return(@repo) + + post :create, format: :js + end + end +end diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb new file mode 100644 index 00000000000..b6b86b1bcee --- /dev/null +++ b/spec/controllers/import/gitlab_controller_spec.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +describe Import::GitlabController do + let(:user) { create(:user, gitlab_access_token: 'asd123') } + + before do + sign_in(user) + controller.stub(:gitlab_import_enabled?).and_return(true) + end + + describe "GET callback" do + it "updates access token" do + token = "asdasd12345" + Gitlab::GitlabImport::Client.any_instance.stub_chain(:client, :auth_code, :get_token, :token).and_return(token) + Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab") + + get :callback + + expect(user.reload.gitlab_access_token).to eq(token) + expect(controller).to redirect_to(status_import_gitlab_url) + end + end + + describe "GET status" do + before do + @repo = OpenStruct.new(path: 'vim', path_with_namespace: 'asd/vim') + end + + it "assigns variables" do + @project = create(:project, import_type: 'gitlab', creator_id: user.id) + controller.stub_chain(:client, :projects).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([@repo]) + end + + it "does not show already added project" do + @project = create(:project, import_type: 'gitlab', creator_id: user.id, import_source: 'asd/vim') + controller.stub_chain(:client, :projects).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([]) + end + end + + describe "POST create" do + before do + @repo = { + path: 'vim', + path_with_namespace: 'asd/vim', + owner: {name: "john"}, + namespace: {path: "john"} + }.with_indifferent_access + end + + it "takes already existing namespace" do + namespace = create(:namespace, name: "john", owner: user) + expect(Gitlab::GitlabImport::ProjectCreator). + to receive(:new).with(@repo, namespace, user). + and_return(double(execute: true)) + controller.stub_chain(:client, :project).and_return(@repo) + + post :create, format: :js + end + end +end diff --git a/spec/controllers/import/gitorious_controller_spec.rb b/spec/controllers/import/gitorious_controller_spec.rb new file mode 100644 index 00000000000..07c9484bf1a --- /dev/null +++ b/spec/controllers/import/gitorious_controller_spec.rb @@ -0,0 +1,67 @@ +require 'spec_helper' + +describe Import::GitoriousController do + let(:user) { create(:user) } + + before do + sign_in(user) + end + + describe "GET new" do + it "redirects to import endpoint on gitorious.org" do + get :new + + expect(controller).to redirect_to("https://gitorious.org/gitlab-import?callback_url=http://test.host/import/gitorious/callback") + end + end + + describe "GET callback" do + it "stores repo list in session" do + get :callback, repos: 'foo/bar,baz/qux' + + expect(session[:gitorious_repos]).to eq('foo/bar,baz/qux') + end + end + + describe "GET status" do + before do + @repo = OpenStruct.new(full_name: 'asd/vim') + end + + it "assigns variables" do + @project = create(:project, import_type: 'gitorious', creator_id: user.id) + controller.stub_chain(:client, :repos).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([@repo]) + end + + it "does not show already added project" do + @project = create(:project, import_type: 'gitorious', creator_id: user.id, import_source: 'asd/vim') + controller.stub_chain(:client, :repos).and_return([@repo]) + + get :status + + expect(assigns(:already_added_projects)).to eq([@project]) + expect(assigns(:repos)).to eq([]) + end + end + + describe "POST create" do + before do + @repo = Gitlab::GitoriousImport::Repository.new('asd/vim') + end + + it "takes already existing namespace" do + namespace = create(:namespace, name: "asd", owner: user) + expect(Gitlab::GitoriousImport::ProjectCreator). + to receive(:new).with(@repo, namespace, user). + and_return(double(execute: true)) + controller.stub_chain(:client, :repo).and_return(@repo) + + post :create, format: :js + end + end +end diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb index 300527e4ff2..d6f56ed33d6 100644 --- a/spec/controllers/merge_requests_controller_spec.rb +++ b/spec/controllers/merge_requests_controller_spec.rb @@ -13,27 +13,32 @@ describe Projects::MergeRequestsController do describe "#show" do shared_examples "export merge as" do |format| it "should generally work" do - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response).to be_success end it "should generate it" do - MergeRequest.any_instance.should_receive(:"to_#{format}") + expect_any_instance_of(MergeRequest).to receive(:"to_#{format}") - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) end it "should render it" do - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response.body).to eq((merge_request.send(:"to_#{format}",user)).to_s) end it "should not escape Html" do - MergeRequest.any_instance.stub(:"to_#{format}").and_return('HTML entities &<>" ') + allow_any_instance_of(MergeRequest).to receive(:"to_#{format}"). + and_return('HTML entities &<>" ') - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response.body).to_not include('&') expect(response.body).to_not include('>') @@ -47,7 +52,8 @@ describe Projects::MergeRequestsController do let(:format) { :diff } it "should really only be a git diff" do - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response.body).to start_with("diff --git") end @@ -58,13 +64,15 @@ describe Projects::MergeRequestsController do let(:format) { :patch } it "should really be a git email patch with commit" do - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response.body[0..100]).to start_with("From #{merge_request.commits.last.id}") end it "should contain git diffs" do - get :show, project_id: project.to_param, id: merge_request.iid, format: format + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: merge_request.iid, format: format) expect(response.body).to match(/^diff --git/) end diff --git a/spec/controllers/projects/protected_branches_controller_spec.rb b/spec/controllers/projects/protected_branches_controller_spec.rb new file mode 100644 index 00000000000..596d8d34b7c --- /dev/null +++ b/spec/controllers/projects/protected_branches_controller_spec.rb @@ -0,0 +1,10 @@ +require('spec_helper') + +describe Projects::ProtectedBranchesController do + describe "GET #index" do + let(:project) { create(:project_empty_repo, :public) } + it "redirect empty repo to projects page" do + get(:index, namespace_id: project.namespace.to_param, project_id: project.to_param) + end + end +end diff --git a/spec/controllers/projects/uploads_controller_spec.rb b/spec/controllers/projects/uploads_controller_spec.rb new file mode 100644 index 00000000000..029f48b2d7a --- /dev/null +++ b/spec/controllers/projects/uploads_controller_spec.rb @@ -0,0 +1,57 @@ +require('spec_helper') + +describe Projects::UploadsController do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + + describe "POST #create" do + before do + sign_in(user) + project.team << [user, :developer] + end + + context "without params['file']" do + it "returns an error" do + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + format: :json + expect(response.status).to eq(422) + end + end + + context 'with valid image' do + before do + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + file: jpg, + format: :json + end + + it 'returns a content with original filename, new link, and correct type.' do + expect(response.body).to match '\"alt\":\"rails_sample\"' + expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads" + expect(response.body).to match '\"is_image\":true' + end + end + + context 'with valid non-image file' do + before do + post :create, + namespace_id: project.namespace.to_param, + project_id: project.to_param, + file: txt, + format: :json + end + + it 'returns a content with original filename, new link, and correct type.' do + expect(response.body).to match '\"alt\":\"doc_sample.txt\"' + expect(response.body).to match "\"url\":\"http://localhost/#{project.path_with_namespace}/uploads" + expect(response.body).to match '\"is_image\":false' + end + end + end +end diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 71bc49787cc..a1b82a32150 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -7,56 +7,41 @@ describe ProjectsController do let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } - describe "POST #upload_image" do - before do - sign_in(user) - project.team << [user, :developer] - end + describe "GET show" do - context "without params['markdown_img']" do - it "returns an error" do - post :upload_image, id: project.to_param, format: :json - expect(response.status).to eq(422) - end - end + context "when requested by `go get`" do + render_views - context "with invalid file" do - before do - post :upload_image, id: project.to_param, markdown_img: txt, format: :json - end + it "renders the go-import meta tag" do + get :show, "go-get" => "1", namespace_id: "bogus_namespace", id: "bogus_project" - it "returns an error" do - expect(response.status).to eq(422) - end - end - - context "with valid file" do - before do - post :upload_image, id: project.to_param, markdown_img: jpg, format: :json - end - - it "returns a content with original filename and new link." do - expect(response.body).to match "\"alt\":\"rails_sample\"" - expect(response.body).to match "\"url\":\"http://test.host/uploads/#{project.path_with_namespace}" + expect(response.body).to include("name='go-import'") + + content = "localhost/bogus_namespace/bogus_project git http://localhost/bogus_namespace/bogus_project.git" + expect(response.body).to include("content='#{content}'") end end end - + describe "POST #toggle_star" do it "toggles star if user is signed in" do sign_in(user) - expect(user.starred?(public_project)).to be_false - post :toggle_star, id: public_project.to_param - expect(user.starred?(public_project)).to be_true - post :toggle_star, id: public_project.to_param - expect(user.starred?(public_project)).to be_false + expect(user.starred?(public_project)).to be_falsey + post(:toggle_star, namespace_id: public_project.namespace.to_param, + id: public_project.to_param) + expect(user.starred?(public_project)).to be_truthy + post(:toggle_star, namespace_id: public_project.namespace.to_param, + id: public_project.to_param) + expect(user.starred?(public_project)).to be_falsey end it "does nothing if user is not signed in" do - post :toggle_star, id: public_project.to_param - expect(user.starred?(public_project)).to be_false - post :toggle_star, id: public_project.to_param - expect(user.starred?(public_project)).to be_false + post(:toggle_star, namespace_id: project.namespace.to_param, + id: public_project.to_param) + expect(user.starred?(public_project)).to be_falsey + post(:toggle_star, namespace_id: project.namespace.to_param, + id: public_project.to_param) + expect(user.starred?(public_project)).to be_falsey end end end diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb index 8147fb0e6fb..7b219819bbc 100644 --- a/spec/controllers/tree_controller_spec.rb +++ b/spec/controllers/tree_controller_spec.rb @@ -9,8 +9,8 @@ describe Projects::TreeController do project.team << [user, :master] - project.stub(:branches).and_return(['master', 'foo/bar/baz']) - project.stub(:tags).and_return(['v1.0.0', 'v2.0.0']) + allow(project).to receive(:branches).and_return(['master', 'foo/bar/baz']) + allow(project).to receive(:tags).and_return(['v1.0.0', 'v2.0.0']) controller.instance_variable_set(:@project, project) end @@ -18,26 +18,29 @@ describe Projects::TreeController do # Make sure any errors accessing the tree in our views bubble up to this spec render_views - before { get :show, project_id: project.to_param, id: id } + before do + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: id) + end context "valid branch, no path" do let(:id) { 'master' } - it { should respond_with(:success) } + it { is_expected.to respond_with(:success) } end context "valid branch, valid path" do let(:id) { 'master/encoding/' } - it { should respond_with(:success) } + it { is_expected.to respond_with(:success) } end context "valid branch, invalid path" do let(:id) { 'master/invalid-path/' } - it { should respond_with(:not_found) } + it { is_expected.to respond_with(:not_found) } end context "invalid branch, valid path" do let(:id) { 'invalid-branch/encoding/' } - it { should respond_with(:not_found) } + it { is_expected.to respond_with(:not_found) } end end @@ -45,12 +48,17 @@ describe Projects::TreeController do render_views before do - get :show, project_id: project.to_param, id: id + get(:show, namespace_id: project.namespace.to_param, + project_id: project.to_param, id: id) end context 'redirect to blob' do let(:id) { 'master/README.md' } - it { should redirect_to("/#{project.path_with_namespace}/blob/master/README.md") } + it 'redirects' do + redirect_url = "/#{project.path_with_namespace}/blob/master/README.md" + expect(subject). + to redirect_to(redirect_url) + end end end end diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb new file mode 100644 index 00000000000..0f9780356b1 --- /dev/null +++ b/spec/controllers/uploads_controller_spec.rb @@ -0,0 +1,296 @@ +require 'spec_helper' + +describe UploadsController do + let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + + describe "GET show" do + context "when viewing a user avatar" do + context "when signed in" do + before do + sign_in(user) + end + + context "when the user is blocked" do + before do + user.block + end + + it "redirects to the sign in page" do + get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when the user isn't blocked" do + it "responds with status 200" do + get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when not signed in" do + it "responds with status 200" do + get :show, model: "user", mounted_as: "avatar", id: user.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when viewing a project avatar" do + let!(:project) { create(:project, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + + context "when the project is public" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) + end + + context "when not signed in" do + it "responds with status 200" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + it "responds with status 200" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the project is private" do + before do + project.update_attribute(:visibility_level, Project::PRIVATE) + end + + context "when not signed in" do + it "redirects to the sign in page" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user has access to the project" do + before do + project.team << [user, :master] + end + + context "when the user is blocked" do + before do + user.block + project.team << [user, :master] + end + + it "redirects to the sign in page" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when the user isn't blocked" do + it "responds with status 200" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the user doesn't have access to the project" do + it "responds with status 404" do + get :show, model: "project", mounted_as: "avatar", id: project.id, filename: "image.png" + + expect(response.status).to eq(404) + end + end + end + end + end + + context "when viewing a group avatar" do + let!(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let!(:project) { create(:project, namespace: group) } + + context "when the group has public projects" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) + end + + context "when not signed in" do + it "responds with status 200" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + it "responds with status 200" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the project doesn't have public projects" do + context "when not signed in" do + it "redirects to the sign in page" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user has access to the project" do + before do + project.team << [user, :master] + end + + context "when the user is blocked" do + before do + user.block + project.team << [user, :master] + end + + it "redirects to the sign in page" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when the user isn't blocked" do + it "responds with status 200" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the user doesn't have access to the project" do + it "responds with status 404" do + get :show, model: "group", mounted_as: "avatar", id: group.id, filename: "image.png" + + expect(response.status).to eq(404) + end + end + end + end + end + + context "when viewing a note attachment" do + let!(:note) { create(:note, :with_attachment) } + let(:project) { note.project } + + context "when the project is public" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) + end + + context "when not signed in" do + it "responds with status 200" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + it "responds with status 200" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the project is private" do + before do + project.update_attribute(:visibility_level, Project::PRIVATE) + end + + context "when not signed in" do + it "redirects to the sign in page" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when signed in" do + before do + sign_in(user) + end + + context "when the user has access to the project" do + before do + project.team << [user, :master] + end + + context "when the user is blocked" do + before do + user.block + project.team << [user, :master] + end + + it "redirects to the sign in page" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response).to redirect_to(new_user_session_path) + end + end + + context "when the user isn't blocked" do + it "responds with status 200" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response.status).to eq(200) + end + end + end + + context "when the user doesn't have access to the project" do + it "responds with status 404" do + get :show, model: "note", mounted_as: "attachment", id: note.id, filename: "image.png" + + expect(response.status).to eq(404) + end + end + end + end + end + end +end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb new file mode 100644 index 00000000000..44225c054f2 --- /dev/null +++ b/spec/controllers/users_controller_spec.rb @@ -0,0 +1,27 @@ +require 'spec_helper' + +describe UsersController do + let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") } + + before do + sign_in(user) + end + + describe "GET #show" do + render_views + + it "renders the show template" do + get :show, username: user.username + expect(response.status).to eq(200) + expect(response).to render_template("show") + end + end + + describe "GET #calendar" do + it "renders calendar" do + get :calendar, username: user.username + expect(response).to render_template("calendar") + end + end +end + diff --git a/spec/factories.rb b/spec/factories.rb index a960571206c..fc103e5b133 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -5,10 +5,14 @@ FactoryGirl.define do Faker::Lorem.sentence end - sequence :name, aliases: [:file_name] do + sequence :name do Faker::Name.name end + sequence :file_name do + Faker::Internet.user_name + end + sequence(:url) { Faker::Internet.uri('http') } factory :user, aliases: [:author, :assignee, :owner, :creator] do @@ -16,7 +20,6 @@ FactoryGirl.define do name sequence(:username) { |n| "#{Faker::Internet.user_name}#{n}" } password "12345678" - password_confirmation { password } confirmed_at { Time.now } confirmation_token { nil } @@ -24,6 +27,20 @@ FactoryGirl.define do admin true end + factory :omniauth_user do + ignore do + extern_uid '123456' + provider 'ldapmain' + end + + after(:create) do |user, evaluator| + user.identities << create(:identity, + provider: evaluator.provider, + extern_uid: evaluator.extern_uid + ) + end + end + factory :admin, traits: [:admin] end @@ -177,4 +194,9 @@ FactoryGirl.define do deploy_key project end + + factory :identity do + provider 'ldapmain' + extern_uid 'my-ldap-id' + end end diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb index 0ae8ea5f878..77cd37c22d9 100644 --- a/spec/factories/merge_requests.rb +++ b/spec/factories/merge_requests.rb @@ -18,6 +18,7 @@ # iid :integer # description :text # position :integer default(0) +# locked_at :datetime # FactoryGirl.define do @@ -39,7 +40,7 @@ FactoryGirl.define do source_branch "master" target_branch "feature" - merge_status :can_be_merged + merge_status "can_be_merged" trait :with_diffs do end diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 83d0cc62dbf..f1c33461b55 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -30,6 +30,7 @@ FactoryGirl.define do factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note] factory :note_on_merge_request, traits: [:on_merge_request] factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff] + factory :note_on_project_snippet, traits: [:on_project_snippet] trait :on_commit do project factory: :project @@ -52,6 +53,11 @@ FactoryGirl.define do noteable_type "Issue" end + trait :on_project_snippet do + noteable_id 1 + noteable_type "Snippet" + end + trait :with_attachment do attachment { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } end diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb index 23314b3b1a4..0899a7603fc 100644 --- a/spec/factories/projects.rb +++ b/spec/factories/projects.rb @@ -24,9 +24,16 @@ # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null +# import_type :string(255) +# import_source :string(255) +# avatar :string(255) # FactoryGirl.define do + # Project without repository + # + # Project does not have bare repository. + # Use this factory if you dont need repository in tests factory :empty_project, class: 'Project' do sequence(:name) { |n| "project#{n}" } path { name.downcase.gsub(/\s/, '_') } @@ -47,6 +54,20 @@ FactoryGirl.define do end end + # Project with empty repository + # + # This is a case when you just created a project + # but not pushed any code there yet + factory :project_empty_repo, parent: :empty_project do + after :create do |project| + project.create_repository + end + end + + # Project with test repository + # + # Test repository source can be found at + # https://gitlab.com/gitlab-org/gitlab-test factory :project, parent: :empty_project do path { 'gitlabhq' } @@ -56,7 +77,19 @@ FactoryGirl.define do end factory :redmine_project, parent: :project do - issues_tracker { "redmine" } - issues_tracker_id { "project_name_in_redmine" } + after :create do |project| + project.create_redmine_service( + active: true, + properties: { + 'project_url' => 'http://redmine/projects/project_name_in_redmine', + 'issues_url' => "http://redmine/#{project.id}/project_name_in_redmine/:id", + 'new_issue_url' => 'http://redmine/projects/project_name_in_redmine/issues/new' + } + ) + end + after :create do |project| + project.issues_tracker = 'redmine' + project.issues_tracker_id = 'project_name_in_redmine' + end end end diff --git a/spec/factories_spec.rb b/spec/factories_spec.rb index 66bef0761c7..c8e218d4d03 100644 --- a/spec/factories_spec.rb +++ b/spec/factories_spec.rb @@ -9,7 +9,7 @@ FactoryGirl.factories.map(&:name).each do |factory_name| next if INVALID_FACTORIES.include?(factory_name) describe "#{factory_name} factory" do it 'should be valid' do - build(factory_name).should be_valid + expect(build(factory_name)).to be_valid end end end diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb index b557567bd04..25862614d28 100644 --- a/spec/features/admin/admin_hooks_spec.rb +++ b/spec/features/admin/admin_hooks_spec.rb @@ -12,15 +12,15 @@ describe "Admin::Hooks", feature: true do describe "GET /admin/hooks" do it "should be ok" do visit admin_root_path - within ".main-nav" do + within ".sidebar-wrapper" do click_on "Hooks" end - current_path.should == admin_hooks_path + expect(current_path).to eq(admin_hooks_path) end it "should have hooks list" do visit admin_hooks_path - page.should have_content(@system_hook.url) + expect(page).to have_content(@system_hook.url) end end @@ -33,8 +33,8 @@ describe "Admin::Hooks", feature: true do end it "should open new hook popup" do - current_path.should == admin_hooks_path - page.should have_content(@url) + expect(current_path).to eq(admin_hooks_path) + expect(page).to have_content(@url) end end @@ -45,7 +45,7 @@ describe "Admin::Hooks", feature: true do click_link "Test Hook" end - it { current_path.should == admin_hooks_path } + it { expect(current_path).to eq(admin_hooks_path) } end end diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb index 3b3d027ab75..101d955d693 100644 --- a/spec/features/admin/admin_projects_spec.rb +++ b/spec/features/admin/admin_projects_spec.rb @@ -8,27 +8,27 @@ describe "Admin::Projects", feature: true do describe "GET /admin/projects" do before do - visit admin_projects_path + visit admin_namespaces_projects_path end it "should be ok" do - current_path.should == admin_projects_path + expect(current_path).to eq(admin_namespaces_projects_path) end it "should have projects list" do - page.should have_content(@project.name) + expect(page).to have_content(@project.name) end end describe "GET /admin/projects/:id" do before do - visit admin_projects_path + visit admin_namespaces_projects_path click_link "#{@project.name}" end it "should have project info" do - page.should have_content(@project.path) - page.should have_content(@project.name) + expect(page).to have_content(@project.path) + expect(page).to have_content(@project.name) end end end diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb index 82da19746f8..f97b69713ce 100644 --- a/spec/features/admin/admin_users_spec.rb +++ b/spec/features/admin/admin_users_spec.rb @@ -9,12 +9,12 @@ describe "Admin::Users", feature: true do end it "should be ok" do - current_path.should == admin_users_path + expect(current_path).to eq(admin_users_path) end it "should have users list" do - page.should have_content(@user.email) - page.should have_content(@user.name) + expect(page).to have_content(@user.email) + expect(page).to have_content(@user.name) end end @@ -32,31 +32,33 @@ describe "Admin::Users", feature: true do it "should apply defaults to user" do click_button "Create user" - user = User.last - user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit - user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group + user = User.find_by(username: 'bang') + expect(user.projects_limit). + to eq(Gitlab.config.gitlab.default_projects_limit) + expect(user.can_create_group). + to eq(Gitlab.config.gitlab.default_can_create_group) end it "should create user with valid data" do click_button "Create user" - user = User.last - user.name.should == "Big Bang" - user.email.should == "bigbang@mail.com" + user = User.find_by(username: 'bang') + expect(user.name).to eq('Big Bang') + expect(user.email).to eq('bigbang@mail.com') end it "should call send mail" do - Notify.should_receive(:new_user_email) + expect(Notify).to receive(:new_user_email) click_button "Create user" end it "should send valid email to user with email & password" do click_button "Create user" - user = User.last + user = User.find_by(username: 'bang') email = ActionMailer::Base.deliveries.last - email.subject.should have_content("Account was created") - email.text_part.body.should have_content(user.email) - email.text_part.body.should have_content('password') + expect(email.subject).to have_content('Account was created') + expect(email.text_part.body).to have_content(user.email) + expect(email.text_part.body).to have_content('password') end end @@ -67,8 +69,8 @@ describe "Admin::Users", feature: true do end it "should have user info" do - page.should have_content(@user.email) - page.should have_content(@user.name) + expect(page).to have_content(@user.email) + expect(page).to have_content(@user.name) end end @@ -80,8 +82,8 @@ describe "Admin::Users", feature: true do end it "should have user edit page" do - page.should have_content("Name") - page.should have_content("Password") + expect(page).to have_content('Name') + expect(page).to have_content('Password') end describe "Update user" do @@ -93,14 +95,14 @@ describe "Admin::Users", feature: true do end it "should show page with new data" do - page.should have_content("bigbang@mail.com") - page.should have_content("Big Bang") + expect(page).to have_content('bigbang@mail.com') + expect(page).to have_content('Big Bang') end it "should change user entry" do @simple_user.reload - @simple_user.name.should == "Big Bang" - @simple_user.is_admin?.should be_true + expect(@simple_user.name).to eq('Big Bang') + expect(@simple_user.is_admin?).to be_truthy end end end diff --git a/spec/features/admin/security_spec.rb b/spec/features/admin/security_spec.rb index 21b0d8b965e..175fa9d4647 100644 --- a/spec/features/admin/security_spec.rb +++ b/spec/features/admin/security_spec.rb @@ -2,26 +2,26 @@ require 'spec_helper' describe "Admin::Projects", feature: true do describe "GET /admin/projects" do - subject { admin_projects_path } + subject { admin_namespaces_projects_path } - it { should be_allowed_for :admin } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /admin/users" do subject { admin_users_path } - it { should be_allowed_for :admin } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /admin/hooks" do subject { admin_hooks_path } - it { should be_allowed_for :admin } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb index 187f2ffcffd..b710cb3c72f 100644 --- a/spec/features/atom/dashboard_issues_spec.rb +++ b/spec/features/atom/dashboard_issues_spec.rb @@ -17,12 +17,13 @@ describe "Dashboard Issues Feed", feature: true do it "should render atom feed via private token" do visit issues_dashboard_path(:atom, private_token: user.private_token) - response_headers['Content-Type'].should have_content("application/atom+xml") - body.should have_selector("title", text: "#{user.name} issues") - body.should have_selector("author email", text: issue1.author_email) - body.should have_selector("entry summary", text: issue1.title) - body.should have_selector("author email", text: issue2.author_email) - body.should have_selector("entry summary", text: issue2.title) + expect(response_headers['Content-Type']). + to have_content('application/atom+xml') + expect(body).to have_selector('title', text: "#{user.name} issues") + expect(body).to have_selector('author email', text: issue1.author_email) + expect(body).to have_selector('entry summary', text: issue1.title) + expect(body).to have_selector('author email', text: issue2.author_email) + expect(body).to have_selector('entry summary', text: issue2.title) end end end diff --git a/spec/features/atom/dashboard_spec.rb b/spec/features/atom/dashboard_spec.rb index a7f87906b2d..ad157d742ff 100644 --- a/spec/features/atom/dashboard_spec.rb +++ b/spec/features/atom/dashboard_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' describe "Dashboard Feed", feature: true do describe "GET /" do - let!(:user) { create(:user) } + let!(:user) { create(:user, name: "Jonh") } context "projects atom feed via private token" do it "should render projects atom feed" do visit dashboard_path(:atom, private_token: user.private_token) - body.should have_selector("feed title") + expect(body).to have_selector('feed title') end end @@ -24,11 +24,12 @@ describe "Dashboard Feed", feature: true do end it "should have issue opened event" do - body.should have_content("#{user.name} opened issue ##{issue.iid}") + expect(body).to have_content("#{user.name} opened issue ##{issue.iid}") end it "should have issue comment event" do - body.should have_content("#{user.name} commented on issue ##{issue.iid}") + expect(body). + to have_content("#{user.name} commented on issue ##{issue.iid}") end end end diff --git a/spec/features/atom/issues_spec.rb b/spec/features/atom/issues_spec.rb index 453dca69094..baa7814e96a 100644 --- a/spec/features/atom/issues_spec.rb +++ b/spec/features/atom/issues_spec.rb @@ -1,33 +1,36 @@ require 'spec_helper' -describe "Issues Feed", feature: true do - describe "GET /issues" do +describe 'Issues Feed', feature: true do + describe 'GET /issues' do let!(:user) { create(:user) } let!(:project) { create(:project) } let!(:issue) { create(:issue, author: user, project: project) } before { project.team << [user, :developer] } - context "when authenticated" do - it "should render atom feed" do + context 'when authenticated' do + it 'should render atom feed' do login_with user - visit project_issues_path(project, :atom) + visit namespace_project_issues_path(project.namespace, project, :atom) - response_headers['Content-Type'].should have_content("application/atom+xml") - body.should have_selector("title", text: "#{project.name} issues") - body.should have_selector("author email", text: issue.author_email) - body.should have_selector("entry summary", text: issue.title) + expect(response_headers['Content-Type']). + to have_content('application/atom+xml') + expect(body).to have_selector('title', text: "#{project.name} issues") + expect(body).to have_selector('author email', text: issue.author_email) + expect(body).to have_selector('entry summary', text: issue.title) end end - context "when authenticated via private token" do - it "should render atom feed" do - visit project_issues_path(project, :atom, private_token: user.private_token) + context 'when authenticated via private token' do + it 'should render atom feed' do + visit namespace_project_issues_path(project.namespace, project, :atom, + private_token: user.private_token) - response_headers['Content-Type'].should have_content("application/atom+xml") - body.should have_selector("title", text: "#{project.name} issues") - body.should have_selector("author email", text: issue.author_email) - body.should have_selector("entry summary", text: issue.title) + expect(response_headers['Content-Type']). + to have_content('application/atom+xml') + expect(body).to have_selector('title', text: "#{project.name} issues") + expect(body).to have_selector('author email', text: issue.author_email) + expect(body).to have_selector('entry summary', text: issue.title) end end end diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb new file mode 100644 index 00000000000..770ac04c2c5 --- /dev/null +++ b/spec/features/atom/users_spec.rb @@ -0,0 +1,77 @@ +require 'spec_helper' + +describe "User Feed", feature: true do + describe "GET /" do + let!(:user) { create(:user) } + + context 'user atom feed via private token' do + it "should render user atom feed" do + visit user_path(user, :atom, private_token: user.private_token) + expect(body).to have_selector('feed title') + end + end + + context 'feed content' do + let(:project) { create(:project) } + let(:issue) do + create(:issue, project: project, + author: user, description: "Houston, we have a bug!\n\n***\n\nI guess.") + end + let(:note) do + create(:note, noteable: issue, author: user, + note: 'Bug confirmed :+1:', project: project) + end + let(:merge_request) do + create(:merge_request, + title: 'Fix bug', author: user, + source_project: project, target_project: project, + description: "Here is the fix: ![an image](image.png)") + end + + before do + project.team << [user, :master] + issue_event(issue, user) + note_event(note, user) + merge_request_event(merge_request, user) + visit user_path(user, :atom, private_token: user.private_token) + end + + it 'should have issue opened event' do + expect(body).to have_content("#{safe_name} opened issue ##{issue.iid}") + end + + it 'should have issue comment event' do + expect(body). + to have_content("#{safe_name} commented on issue ##{issue.iid}") + end + + it 'should have XHTML summaries in issue descriptions' do + expect(body).to match /we have a bug!<\/p>\n\n<hr ?\/>\n\n<p>I guess/ + end + + it 'should have XHTML summaries in notes' do + expect(body).to match /Bug confirmed <img[^>]*\/>/ + end + + it 'should have XHTML summaries in merge request descriptions' do + expect(body).to match /Here is the fix: <img[^>]*\/>/ + end + end + end + + def issue_event(issue, user) + EventCreateService.new.open_issue(issue, user) + end + + def note_event(note, user) + EventCreateService.new.leave_note(note, user) + end + + def merge_request_event(request, user) + EventCreateService.new.open_mr(request, user) + end + + def safe_name + html_escape(user.name) + end +end diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb index 9f50d1c9738..fca1a06eb88 100644 --- a/spec/features/gitlab_flavored_markdown_spec.rb +++ b/spec/features/gitlab_flavored_markdown_spec.rb @@ -23,27 +23,27 @@ describe "GitLab Flavored Markdown", feature: true do describe "for commits" do it "should render title in commits#index" do - visit project_commits_path(project, 'master', limit: 1) + visit namespace_project_commits_path(project.namespace, project, 'master', limit: 1) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end it "should render title in commits#show" do - visit project_commit_path(project, commit) + visit namespace_project_commit_path(project.namespace, project, commit) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end it "should render description in commits#show" do - visit project_commit_path(project, commit) + visit namespace_project_commit_path(project.namespace, project, commit) - page.should have_link("@#{fred.username}") + expect(page).to have_link("@#{fred.username}") end it "should render title in repositories#branches" do - visit project_branches_path(project) + visit namespace_project_branches_path(project.namespace, project) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end end @@ -62,21 +62,21 @@ describe "GitLab Flavored Markdown", feature: true do end it "should render subject in issues#index" do - visit project_issues_path(project) + visit namespace_project_issues_path(project.namespace, project) - page.should have_link("##{@other_issue.iid}") + expect(page).to have_link("##{@other_issue.iid}") end it "should render subject in issues#show" do - visit project_issue_path(project, @issue) + visit namespace_project_issue_path(project.namespace, project, @issue) - page.should have_link("##{@other_issue.iid}") + expect(page).to have_link("##{@other_issue.iid}") end it "should render details in issues#show" do - visit project_issue_path(project, @issue) + visit namespace_project_issue_path(project.namespace, project, @issue) - page.should have_link("@#{fred.username}") + expect(page).to have_link("@#{fred.username}") end end @@ -87,15 +87,15 @@ describe "GitLab Flavored Markdown", feature: true do end it "should render title in merge_requests#index" do - visit project_merge_requests_path(project) + visit namespace_project_merge_requests_path(project.namespace, project) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end it "should render title in merge_requests#show" do - visit project_merge_request_path(project, @merge_request) + visit namespace_project_merge_request_path(project.namespace, project, @merge_request) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end end @@ -109,21 +109,21 @@ describe "GitLab Flavored Markdown", feature: true do end it "should render title in milestones#index" do - visit project_milestones_path(project) + visit namespace_project_milestones_path(project.namespace, project) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end it "should render title in milestones#show" do - visit project_milestone_path(project, @milestone) + visit namespace_project_milestone_path(project.namespace, project, @milestone) - page.should have_link("##{issue.iid}") + expect(page).to have_link("##{issue.iid}") end it "should render description in milestones#show" do - visit project_milestone_path(project, @milestone) + visit namespace_project_milestone_path(project.namespace, project, @milestone) - page.should have_link("@#{fred.username}") + expect(page).to have_link("@#{fred.username}") end end end diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb new file mode 100644 index 00000000000..41088ce8271 --- /dev/null +++ b/spec/features/help_pages_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe 'Help Pages', feature: true do + describe 'Show SSH page' do + before do + login_as :user + end + it 'replace the variable $your_email with the email of the user' do + visit help_page_path(category: 'ssh', file: 'README.md') + expect(page).to have_content("ssh-keygen -t rsa -C \"#{@user.email}\"") + end + end +end diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb index 26607b0090c..a2db57ad908 100644 --- a/spec/features/issues_spec.rb +++ b/spec/features/issues_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' -describe "Issues", feature: true do +describe 'Issues', feature: true do + include SortingHelper + let(:project) { create(:project) } before do @@ -10,7 +12,7 @@ describe "Issues", feature: true do project.team << [[@user, user2], :developer] end - describe "Edit issue" do + describe 'Edit issue' do let!(:issue) do create(:issue, author: @user, @@ -19,34 +21,38 @@ describe "Issues", feature: true do end before do - visit project_issues_path(project) + visit namespace_project_issues_path(project.namespace, project) click_link "Edit" end - it "should open new issue popup" do - page.should have_content("Issue ##{issue.iid}") + it 'should open new issue popup' do + expect(page).to have_content("Issue ##{issue.iid}") end - describe "fill in" do + describe 'fill in' do before do - fill_in "issue_title", with: "bug 345" - fill_in "issue_description", with: "bug description" + fill_in 'issue_title', with: 'bug 345' + fill_in 'issue_description', with: 'bug description' end - it { expect { click_button "Save changes" }.to_not change {Issue.count} } + 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" + it 'should update issue fields' do + click_button 'Save changes' - page.should have_content @user.name - page.should have_content "bug 345" - page.should have_content project.name + 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 + describe 'Editing issue assignee' do let!(:issue) do create(:issue, author: @user, @@ -54,23 +60,23 @@ describe "Issues", feature: true do project: project) end - it 'allows user to select unasigned', :js => true do - visit edit_project_issue_path(project, issue) + it 'allows user to select unasigned', js: true do + visit edit_namespace_project_issue_path(project.namespace, project, issue) - page.should have_content "Assign to #{@user.name}" + expect(page).to have_content "Assign to #{@user.name}" first('#s2id_issue_assignee_id').click sleep 2 # wait for ajax stuff to complete first('.user-result').click - click_button "Save changes" + click_button 'Save changes' - page.should have_content "Assignee: Select assignee" - issue.reload.assignee.should be_nil + expect(page).to have_content 'Assignee: none' + expect(issue.reload.assignee).to be_nil end end - describe "Filter issue" do + describe 'Filter issue' do before do ['foobar', 'barbaz', 'gitlab'].each do |title| create(:issue, @@ -80,7 +86,7 @@ describe "Issues", feature: true do title: title) end - @issue = Issue.first # with title 'foobar' + @issue = Issue.find_by(title: 'foobar') @issue.milestone = create(:milestone, project: project) @issue.assignee = nil @issue.save @@ -88,75 +94,79 @@ describe "Issues", feature: true do let(:issue) { @issue } - it "should allow filtering by issues with no specified milestone" do - visit project_issues_path(project, milestone_id: '0') + it 'should allow filtering by issues with no specified milestone' do + visit namespace_project_issues_path(project.namespace, project, milestone_id: '0') - page.should_not have_content 'foobar' - page.should have_content 'barbaz' - page.should have_content 'gitlab' + expect(page).not_to have_content 'foobar' + expect(page).to have_content 'barbaz' + expect(page).to have_content 'gitlab' end - it "should allow filtering by a specified milestone" do - visit project_issues_path(project, milestone_id: issue.milestone.id) + it 'should allow filtering by a specified milestone' do + visit namespace_project_issues_path(project.namespace, project, milestone_id: issue.milestone.id) - page.should have_content 'foobar' - page.should_not have_content 'barbaz' - page.should_not have_content 'gitlab' + expect(page).to have_content 'foobar' + expect(page).not_to have_content 'barbaz' + expect(page).not_to have_content 'gitlab' end - it "should allow filtering by issues with no specified assignee" do - visit project_issues_path(project, assignee_id: '0') + it 'should allow filtering by issues with no specified assignee' do + visit namespace_project_issues_path(project.namespace, project, assignee_id: '0') - page.should have_content 'foobar' - page.should_not have_content 'barbaz' - page.should_not have_content 'gitlab' + expect(page).to have_content 'foobar' + expect(page).not_to have_content 'barbaz' + expect(page).not_to have_content 'gitlab' end - it "should allow filtering by a specified assignee" do - visit project_issues_path(project, assignee_id: @user.id) + it 'should allow filtering by a specified assignee' do + visit namespace_project_issues_path(project.namespace, project, assignee_id: @user.id) - page.should_not have_content 'foobar' - page.should have_content 'barbaz' - page.should have_content 'gitlab' + expect(page).not_to have_content 'foobar' + expect(page).to have_content 'barbaz' + expect(page).to have_content 'gitlab' end end describe 'filter issue' do titles = ['foo','bar','baz'] titles.each_with_index do |title, index| - let!(title.to_sym) { create(:issue, title: title, project: project, created_at: Time.now - (index * 60)) } + let!(title.to_sym) do + create(:issue, title: title, + project: project, + created_at: Time.now - (index * 60)) + end end let(:newer_due_milestone) { create(:milestone, due_date: '2013-12-11') } let(:later_due_milestone) { create(:milestone, due_date: '2013-12-12') } it 'sorts by newest' do - visit project_issues_path(project, sort: 'newest') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_created) - first_issue.should include("foo") - last_issue.should include("baz") + expect(first_issue).to include('foo') + expect(last_issue).to include('baz') end it 'sorts by oldest' do - visit project_issues_path(project, sort: 'oldest') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_created) - first_issue.should include("baz") - last_issue.should include("foo") + expect(first_issue).to include('baz') + expect(last_issue).to include('foo') end it 'sorts by most recently updated' do baz.updated_at = Time.now + 100 baz.save - visit project_issues_path(project, sort: 'recently_updated') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_recently_updated) - first_issue.should include("baz") + expect(first_issue).to include('baz') end it 'sorts by least recently updated' do baz.updated_at = Time.now - 100 baz.save - visit project_issues_path(project, sort: 'last_updated') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_oldest_updated) - first_issue.should include("baz") + expect(first_issue).to include('baz') end describe 'sorting by milestone' do @@ -168,15 +178,15 @@ describe "Issues", feature: true do end it 'sorts by recently due milestone' do - visit project_issues_path(project, sort: 'milestone_due_soon') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon) - first_issue.should include("foo") + expect(first_issue).to include('foo') end it 'sorts by least recently due milestone' do - visit project_issues_path(project, sort: 'milestone_due_later') + visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later) - first_issue.should include("bar") + expect(first_issue).to include('bar') end end @@ -191,11 +201,13 @@ describe "Issues", feature: true do end it 'sorts with a filter applied' do - visit project_issues_path(project, sort: 'oldest', assignee_id: user2.id) + visit namespace_project_issues_path(project.namespace, project, + sort: sort_value_oldest_created, + assignee_id: user2.id) - first_issue.should include("bar") - last_issue.should include("foo") - page.should_not have_content 'baz' + expect(first_issue).to include('bar') + expect(last_issue).to include('foo') + expect(page).not_to have_content 'baz' end end end @@ -206,13 +218,15 @@ describe "Issues", feature: true do context 'by autorized user' do it 'with dropdown menu' do - visit project_issue_path(project, issue) + visit namespace_project_issue_path(project.namespace, project, issue) - find('.edit-issue.inline-update #issue_assignee_id').set project.team.members.first.id + find('.edit-issue.inline-update #issue_assignee_id'). + set project.team.members.first.id click_button 'Update Issue' - page.should have_content "Assignee:" - has_select?('issue_assignee_id', :selected => project.team.members.first.name) + expect(page).to have_content 'Assignee:' + has_select?('issue_assignee_id', + selected: project.team.members.first.name) end end @@ -226,12 +240,12 @@ describe "Issues", feature: true do issue.save end - it "shows assignee text", js: true do + it 'shows assignee text', js: true do logout login_with guest - visit project_issue_path(project, issue) - page.should have_content issue.assignee.name + visit namespace_project_issue_path(project.namespace, project, issue) + expect(page).to have_content issue.assignee.name end end end @@ -243,13 +257,15 @@ describe "Issues", feature: true do context 'by authorized user' do it 'with dropdown menu' do - visit project_issue_path(project, issue) + visit namespace_project_issue_path(project.namespace, project, issue) - find('.edit-issue.inline-update').select(milestone.title, from: 'issue_milestone_id') + find('.edit-issue.inline-update'). + select(milestone.title, from: 'issue_milestone_id') click_button 'Update Issue' - page.should have_content "Milestone changed to #{milestone.title}" - has_select?('issue_assignee_id', :selected => milestone.title) + expect(page).to have_content "Milestone changed to #{milestone.title}" + expect(page).to have_content "Milestone: #{milestone.title}" + has_select?('issue_assignee_id', selected: milestone.title) end end @@ -262,12 +278,12 @@ describe "Issues", feature: true do issue.save end - it "shows milestone text", js: true do + it 'shows milestone text', js: true do logout login_with guest - visit project_issue_path(project, issue) - page.should have_content milestone.title + visit namespace_project_issue_path(project.namespace, project, issue) + expect(page).to have_content milestone.title end end @@ -280,25 +296,25 @@ describe "Issues", feature: true do end it 'allows user to remove assignee', :js => true do - visit project_issue_path(project, issue) - page.should have_content "Assignee: #{user2.name}" + visit namespace_project_issue_path(project.namespace, project, issue) + expect(page).to have_content "Assignee: #{user2.name}" first('#s2id_issue_assignee_id').click sleep 2 # wait for ajax stuff to complete first('.user-result').click - page.should have_content "Assignee: Unassigned" + expect(page).to have_content 'Assignee: none' sleep 2 # wait for ajax stuff to complete - issue.reload.assignee.should be_nil + expect(issue.reload.assignee).to be_nil end end end def first_issue - all("ul.issues-list li").first.text + all('ul.issues-list li').first.text end def last_issue - all("ul.issues-list li").last.text + all('ul.issues-list li').last.text end end diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb index 92f3a6c0929..c47368b1fda 100644 --- a/spec/features/notes_on_merge_requests_spec.rb +++ b/spec/features/notes_on_merge_requests_spec.rb @@ -3,197 +3,213 @@ require 'spec_helper' describe 'Comments' do include RepoHelpers - describe "On a merge request", js: true, feature: true do + describe 'On a merge request', js: true, feature: true do let!(:merge_request) { create(:merge_request) } let!(:project) { merge_request.source_project } - let!(:note) { create(:note_on_merge_request, :with_attachment, project: project) } + let!(:note) do + create(:note_on_merge_request, :with_attachment, project: project) + end before do login_as :admin - visit project_merge_request_path(project, merge_request) + visit namespace_project_merge_request_path(project.namespace, project, merge_request) end subject { page } - describe "the note form" do + describe 'the note form' do it 'should be valid' do - should have_css(".js-main-target-form", visible: true, count: 1) - find(".js-main-target-form input[type=submit]").value.should == "Add Comment" - within(".js-main-target-form") { should_not have_link("Cancel") } - within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: false) } + is_expected.to have_css('.js-main-target-form', visible: true, count: 1) + expect(find('.js-main-target-form input[type=submit]').value). + to eq('Add Comment') + within('.js-main-target-form') do + expect(page).not_to have_link('Cancel') + end end - describe "with text" do + describe 'with text' do before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awesome" + within('.js-main-target-form') do + fill_in 'note[note]', with: 'This is awesome' end end it 'should have enable submit button and preview button' do - within(".js-main-target-form") { should_not have_css(".js-comment-button[disabled]") } - within(".js-main-target-form") { should have_css(".js-note-preview-button", visible: true) } + within('.js-main-target-form') do + expect(page).not_to have_css('.js-comment-button[disabled]') + expect(page).to have_css('.js-md-preview-button', visible: true) + end end end end - describe "when posting a note" do + describe 'when posting a note' do before do - within(".js-main-target-form") do - fill_in "note[note]", with: "This is awsome!" - find(".js-note-preview-button").trigger("click") - click_button "Add Comment" + within('.js-main-target-form') do + fill_in 'note[note]', with: 'This is awsome!' + find('.js-md-preview-button').click + click_button 'Add Comment' end end it 'should be added and form reset' do - should have_content("This is awsome!") - within(".js-main-target-form") { should have_no_field("note[note]", with: "This is awesome!") } - within(".js-main-target-form") { should have_css(".js-note-preview", visible: false) } - within(".js-main-target-form") { should have_css(".js-note-text", visible: true) } + is_expected.to have_content('This is awsome!') + within('.js-main-target-form') do + expect(page).to have_no_field('note[note]', with: 'This is awesome!') + expect(page).to have_css('.js-md-preview', visible: :hidden) + end + within('.js-main-target-form') do + is_expected.to have_css('.js-note-text', visible: true) + end end end - describe "when editing a note", js: true do - it "should contain the hidden edit form" do - within("#note_#{note.id}") { should have_css(".note-edit-form", visible: false) } + describe 'when editing a note', js: true do + it 'should contain the hidden edit form' do + within("#note_#{note.id}") do + is_expected.to have_css('.note-edit-form', visible: false) + end end - describe "editing the note" do + describe 'editing the note' do before do find('.note').hover find(".js-note-edit").click end - it "should show the note edit form and hide the note body" do + it 'should show the note edit form and hide the note body' do within("#note_#{note.id}") do - find(".note-edit-form", visible: true).should be_visible - find(".note-text", visible: false).should_not be_visible - end - end - - it "should reset the edit note form textarea with the original content of the note if cancelled" do - find('.note').hover - find(".js-note-edit").click - - within(".note-edit-form") do - fill_in "note[note]", with: "Some new content" - find(".btn-cancel").click - find(".js-note-text", visible: false).text.should == note.note + expect(find('.current-note-edit-form', visible: true)).to be_visible + expect(find('.note-edit-form', visible: true)).to be_visible + expect(find(:css, '.note-body > .note-text', visible: false)).not_to be_visible end end - it "appends the edited at time to the note" do - find('.note').hover - find(".js-note-edit").click - - within(".note-edit-form") do - fill_in "note[note]", with: "Some new content" - find(".btn-save").click + # TODO: fix after 7.7 release + #it "should reset the edit note form textarea with the original content of the note if cancelled" do + #within(".current-note-edit-form") do + #fill_in "note[note]", with: "Some new content" + #find(".btn-cancel").click + #find(".js-note-text", visible: false).text.should == note.note + #end + #end + + it 'appends the edited at time to the note' do + within('.current-note-edit-form') do + fill_in 'note[note]', with: 'Some new content' + find('.btn-save').click end within("#note_#{note.id}") do - should have_css(".note-last-update small") - find(".note-last-update small").text.should match(/Edited less than a minute ago/) + is_expected.to have_css('.note_edited_ago') + expect(find('.note_edited_ago').text). + to match(/less than a minute ago/) end end end - describe "deleting an attachment" do + describe 'deleting an attachment' do before do find('.note').hover - find(".js-note-edit").click + find('.js-note-edit').click end - it "shows the delete link" do - within(".note-attachment") do - should have_css(".js-note-attachment-delete") + it 'shows the delete link' do + within('.note-attachment') do + is_expected.to have_css('.js-note-attachment-delete') end end - it "removes the attachment div and resets the edit form" do - find(".js-note-attachment-delete").click - should_not have_css(".note-attachment") - find(".note-edit-form", visible: false).should_not be_visible + it 'removes the attachment div and resets the edit form' do + find('.js-note-attachment-delete').click + is_expected.not_to have_css('.note-attachment') + expect(find('.current-note-edit-form', visible: false)). + not_to be_visible end end end end - describe "On a merge request diff", js: true, feature: true do + describe 'On a merge request diff', js: true, feature: true do let(:merge_request) { create(:merge_request) } let(:project) { merge_request.source_project } before do login_as :admin - visit diffs_project_merge_request_path(project, merge_request) + visit diffs_namespace_project_merge_request_path(project.namespace, project, merge_request) end subject { page } - describe "when adding a note" do + describe 'when adding a note' do before do click_diff_line end - describe "the notes holder" do - it { should have_css(".js-temp-notes-holder") } + describe 'the notes holder' do + it { is_expected.to have_css('.js-temp-notes-holder') } - it { within(".js-temp-notes-holder") { should have_css(".new_note") } } + it 'has .new_note css class' do + within('.js-temp-notes-holder') do + expect(subject).to have_css('.new_note') + end + end end - describe "the note form" do + describe 'the note form' do it "shouldn't add a second form for same row" do click_diff_line - should have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form", count: 1) + is_expected. + to have_css("tr[id='#{line_code}'] + .js-temp-notes-holder form", + count: 1) end - it "should be removed when canceled" do + it 'should be removed when canceled' do within(".diff-file form[rel$='#{line_code}']") do - find(".js-close-discussion-note-form").trigger("click") + find('.js-close-discussion-note-form').trigger('click') end - should have_no_css(".js-temp-notes-holder") + is_expected.to have_no_css('.js-temp-notes-holder') end end end - describe "with muliple note forms" do + describe 'with muliple note forms' do before do click_diff_line click_diff_line(line_code_2) end - it { should have_css(".js-temp-notes-holder", count: 2) } + it { is_expected.to have_css('.js-temp-notes-holder', count: 2) } - describe "previewing them separately" do + describe 'previewing them separately' do before do # add two separate texts and trigger previews on both within("tr[id='#{line_code}'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "One comment on line 7" - find(".js-note-preview-button").trigger("click") + fill_in 'note[note]', with: 'One comment on line 7' + find('.js-md-preview-button').click end within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 10" - find(".js-note-preview-button").trigger("click") + fill_in 'note[note]', with: 'Another comment on line 10' + find('.js-md-preview-button').click end end end - describe "posting a note" do + describe 'posting a note' do before do within("tr[id='#{line_code_2}'] + .js-temp-notes-holder") do - fill_in "note[note]", with: "Another comment on line 10" - click_button("Add Comment") + fill_in 'note[note]', with: 'Another comment on line 10' + click_button('Add Comment') end end it 'should be added as discussion' do - should have_content("Another comment on line 10") - should have_css(".notes_holder") - should have_css(".notes_holder .note", count: 1) - should have_button('Reply') + is_expected.to have_content('Another comment on line 10') + is_expected.to have_css('.notes_holder') + is_expected.to have_css('.notes_holder .note', count: 1) + is_expected.to have_button('Reply') end end end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index bdf7b59114b..3d36a3c02d0 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -1,35 +1,35 @@ require 'spec_helper' -describe "Profile account page", feature: true do +describe 'Profile account page', feature: true do let(:user) { create(:user) } before do login_as :user end - describe "when signup is enabled" do + describe 'when signup is enabled' do before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) + ApplicationSetting.any_instance.stub(signup_enabled?: true) visit profile_account_path end - it { page.should have_content("Remove account") } + it { expect(page).to have_content('Remove account') } - it "should delete the account" do - expect { click_link "Delete account" }.to change {User.count}.by(-1) - current_path.should == new_user_session_path + it 'should delete the account' do + expect { click_link 'Delete account' }.to change { User.count }.by(-1) + expect(current_path).to eq(new_user_session_path) end end - describe "when signup is disabled" do + describe 'when signup is disabled' do before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) + ApplicationSetting.any_instance.stub(signup_enabled?: false) visit profile_account_path end - it "should not have option to remove account" do - page.should_not have_content("Remove account") - current_path.should == profile_account_path + it 'should not have option to remove account' do + expect(page).not_to have_content('Remove account') + expect(current_path).to eq(profile_account_path) end end end diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index 98ba5a47ee5..cae11be7cdd 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -1,21 +1,32 @@ require 'spec_helper' -describe "Projects", feature: true do +describe "Projects", feature: true, js: true do before { login_as :user } describe "DELETE /projects/:id" do before do @project = create(:project, namespace: @user.namespace) @project.team << [@user, :master] - visit edit_project_path(@project) + visit edit_namespace_project_path(@project.namespace, @project) end - it "should be correct path", js: true do - expect { - click_link "Remove project" - fill_in 'confirm_name_input', with: @project.path - click_button 'Confirm' - }.to change {Project.count}.by(-1) + it "should remove project" do + expect { remove_project }.to change {Project.count}.by(-1) end + + it 'should delete the project from disk' do + expect(GitlabShellWorker).to( + receive(:perform_async).with(:remove_repository, + /#{@project.path_with_namespace}/) + ).twice + + remove_project + end + end + + def remove_project + click_link "Remove project" + fill_in 'confirm_name_input', with: @project.path + click_button 'Confirm' end end diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb index cce9f06cb69..73987739a7a 100644 --- a/spec/features/search_spec.rb +++ b/spec/features/search_spec.rb @@ -14,7 +14,7 @@ describe "Search", feature: true do end it "should show project in search results" do - page.should have_content @project.name + expect(page).to have_content @project.name end end diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb index 1cca82cef64..67238e3ab76 100644 --- a/spec/features/security/dashboard_access_spec.rb +++ b/spec/features/security/dashboard_access_spec.rb @@ -4,52 +4,60 @@ describe "Dashboard access", feature: true do describe "GET /dashboard" do subject { dashboard_path } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /dashboard/issues" do subject { issues_dashboard_path } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /dashboard/merge_requests" do subject { merge_requests_dashboard_path } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end - describe "GET /dashboard/projects" do - subject { projects_dashboard_path } + describe "GET /dashboard/projects/starred" do + subject { starred_dashboard_projects_path } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /help" do subject { help_path } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /projects/new" do - it { new_project_path.should be_allowed_for :admin } - it { new_project_path.should be_allowed_for :user } - it { new_project_path.should be_denied_for :visitor } + it { expect(new_project_path).to be_allowed_for :admin } + it { expect(new_project_path).to be_allowed_for :user } + it { expect(new_project_path).to be_denied_for :visitor } end describe "GET /groups/new" do - it { new_group_path.should be_allowed_for :admin } - it { new_group_path.should be_allowed_for :user } - it { new_group_path.should be_denied_for :visitor } + it { expect(new_group_path).to be_allowed_for :admin } + it { expect(new_group_path).to be_allowed_for :user } + it { expect(new_group_path).to be_denied_for :visitor } + end + + describe "GET /profile/groups" do + subject { dashboard_groups_path } + + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/security/group/group_access_spec.rb b/spec/features/security/group/group_access_spec.rb index 44de499e6d2..63793149459 100644 --- a/spec/features/security/group/group_access_spec.rb +++ b/spec/features/security/group/group_access_spec.rb @@ -2,9 +2,9 @@ require 'spec_helper' describe "Group access", feature: true do describe "GET /projects/new" do - it { new_group_path.should be_allowed_for :admin } - it { new_group_path.should be_allowed_for :user } - it { new_group_path.should be_denied_for :visitor } + it { expect(new_group_path).to be_allowed_for :admin } + it { expect(new_group_path).to be_allowed_for :user } + it { expect(new_group_path).to be_denied_for :visitor } end describe "Group" do @@ -26,73 +26,73 @@ describe "Group access", feature: true do describe "GET /groups/:path" do subject { group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/issues" do subject { issues_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/merge_requests" do subject { merge_requests_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end - describe "GET /groups/:path/members" do - subject { members_group_path(group) } + describe "GET /groups/:path/group_members" do + subject { group_group_members_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/edit" do subject { edit_group_path(group) } - it { should be_allowed_for owner } - it { should be_denied_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_denied_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/projects" do subject { projects_group_path(group) } - it { should be_allowed_for owner } - it { should be_denied_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_denied_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end end diff --git a/spec/features/security/group/internal_group_access_spec.rb b/spec/features/security/group/internal_group_access_spec.rb index da5c6eb4e91..d17a7412e43 100644 --- a/spec/features/security/group/internal_group_access_spec.rb +++ b/spec/features/security/group/internal_group_access_spec.rb @@ -22,61 +22,61 @@ describe "Group with internal project access", feature: true do describe "GET /groups/:path" do subject { group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/issues" do subject { issues_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/merge_requests" do subject { merge_requests_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end - describe "GET /groups/:path/members" do - subject { members_group_path(group) } + describe "GET /groups/:path/group_members" do + subject { group_group_members_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /groups/:path/edit" do subject { edit_group_path(group) } - it { should be_allowed_for owner } - it { should be_denied_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_denied_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end end diff --git a/spec/features/security/group/mixed_group_access_spec.rb b/spec/features/security/group/mixed_group_access_spec.rb index c9889d99590..b3db7b5dea4 100644 --- a/spec/features/security/group/mixed_group_access_spec.rb +++ b/spec/features/security/group/mixed_group_access_spec.rb @@ -23,61 +23,61 @@ describe "Group access", feature: true do describe "GET /groups/:path" do subject { group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/issues" do subject { issues_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/merge_requests" do subject { merge_requests_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end - describe "GET /groups/:path/members" do - subject { members_group_path(group) } + describe "GET /groups/:path/group_members" do + subject { group_group_members_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/edit" do subject { edit_group_path(group) } - it { should be_allowed_for owner } - it { should be_denied_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_denied_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end end diff --git a/spec/features/security/group/public_group_access_spec.rb b/spec/features/security/group/public_group_access_spec.rb index 2e76ab154ff..c16f0c0d1e1 100644 --- a/spec/features/security/group/public_group_access_spec.rb +++ b/spec/features/security/group/public_group_access_spec.rb @@ -22,61 +22,61 @@ describe "Group with public project access", feature: true do describe "GET /groups/:path" do subject { group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/issues" do subject { issues_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/merge_requests" do subject { merge_requests_group_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end - describe "GET /groups/:path/members" do - subject { members_group_path(group) } + describe "GET /groups/:path/group_members" do + subject { group_group_members_path(group) } - it { should be_allowed_for owner } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /groups/:path/edit" do subject { edit_group_path(group) } - it { should be_allowed_for owner } - it { should be_denied_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for owner } + it { is_expected.to be_denied_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end end diff --git a/spec/features/security/profile_access_spec.rb b/spec/features/security/profile_access_spec.rb index 4efc0ffdcd3..2512a9c0e3d 100644 --- a/spec/features/security/profile_access_spec.rb +++ b/spec/features/security/profile_access_spec.rb @@ -1,76 +1,65 @@ require 'spec_helper' -describe "Users Security", feature: true do - describe "Project" do - before do - @u1 = create(:user) - end - - describe "GET /login" do - it { new_user_session_path.should_not be_404_for :visitor } - end - - describe "GET /profile/keys" do - subject { profile_keys_path } +describe "Profile access", feature: true do + before do + @u1 = create(:user) + end - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + describe "GET /login" do + it { expect(new_user_session_path).not_to be_404_for :visitor } + end - describe "GET /profile" do - subject { profile_path } + describe "GET /profile/keys" do + subject { profile_keys_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end - describe "GET /profile/account" do - subject { profile_account_path } + describe "GET /profile" do + subject { profile_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end - describe "GET /profile/design" do - subject { design_profile_path } + describe "GET /profile/account" do + subject { profile_account_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end - describe "GET /profile/history" do - subject { history_profile_path } + describe "GET /profile/design" do + subject { design_profile_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end - describe "GET /profile/notifications" do - subject { profile_notifications_path } + describe "GET /profile/history" do + subject { history_profile_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } + end - describe "GET /profile/groups" do - subject { profile_groups_path } + describe "GET /profile/notifications" do + subject { profile_notifications_path } - it { should be_allowed_for @u1 } - it { should be_allowed_for :admin } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } - end + it { is_expected.to be_allowed_for @u1 } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 598d554a946..8d1bfd25223 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -18,207 +18,210 @@ describe "Internal Project Access", feature: true do describe "Project should be internal" do subject { project } - its(:internal?) { should be_true } + describe '#internal?' do + subject { super().internal? } + it { is_expected.to be_truthy } + end end describe "GET /:project_path" do - subject { project_path(project) } + subject { namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/tree/master" do - subject { project_tree_path(project, project.repository.root_ref) } + subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/commits/master" do - subject { project_commits_path(project, project.repository.root_ref, limit: 1) } + subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/commit/:sha" do - subject { project_commit_path(project, project.repository.commit) } + subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/compare" do - subject { project_compare_index_path(project) } + subject { namespace_project_compare_index_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/team" do - subject { project_team_index_path(project) } + describe "GET /:project_path/project_members" do + subject { namespace_project_project_members_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/blob" do before do commit = project.repository.commit path = '.gitignore' - @blob_path = project_blob_path(project, File.join(commit.id, path)) + @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path)) end - it { @blob_path.should be_allowed_for master } - it { @blob_path.should be_allowed_for reporter } - it { @blob_path.should be_allowed_for :admin } - it { @blob_path.should be_allowed_for guest } - it { @blob_path.should be_allowed_for :user } - it { @blob_path.should be_denied_for :visitor } + it { expect(@blob_path).to be_allowed_for master } + it { expect(@blob_path).to be_allowed_for reporter } + it { expect(@blob_path).to be_allowed_for :admin } + it { expect(@blob_path).to be_allowed_for guest } + it { expect(@blob_path).to be_allowed_for :user } + it { expect(@blob_path).to be_denied_for :visitor } end describe "GET /:project_path/edit" do - subject { edit_project_path(project) } + subject { edit_namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/deploy_keys" do - subject { project_deploy_keys_path(project) } + subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/issues" do - subject { project_issues_path(project) } + subject { namespace_project_issues_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/snippets" do - subject { project_snippets_path(project) } + subject { namespace_project_snippets_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/snippets/new" do - subject { new_project_snippet_path(project) } + subject { new_namespace_project_snippet_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/merge_requests" do - subject { project_merge_requests_path(project) } + subject { namespace_project_merge_requests_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/merge_requests/new" do - subject { new_project_merge_request_path(project) } + subject { new_namespace_project_merge_request_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/branches" do - subject { project_branches_path(project) } + subject { namespace_project_branches_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:branches).and_return([]) + allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/tags" do - subject { project_tags_path(project) } + subject { namespace_project_tags_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:tags).and_return([]) + allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/hooks" do - subject { project_hooks_path(project) } - - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + subject { namespace_project_hooks_path(project.namespace, project) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + 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 b1d4c79e05b..9021ff33186 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -18,185 +18,188 @@ describe "Private Project Access", feature: true do describe "Project should be private" do subject { project } - its(:private?) { should be_true } + describe '#private?' do + subject { super().private? } + it { is_expected.to be_truthy } + end end describe "GET /:project_path" do - subject { project_path(project) } + subject { namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/tree/master" do - subject { project_tree_path(project, project.repository.root_ref) } + subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/commits/master" do - subject { project_commits_path(project, project.repository.root_ref, limit: 1) } + subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/commit/:sha" do - subject { project_commit_path(project, project.repository.commit) } + subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/compare" do - subject { project_compare_index_path(project) } + subject { namespace_project_compare_index_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end - describe "GET /:project_path/team" do - subject { project_team_index_path(project) } + describe "GET /:project_path/project_members" do + subject { namespace_project_project_members_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/blob" do before do commit = project.repository.commit path = '.gitignore' - @blob_path = project_blob_path(project, File.join(commit.id, path)) + @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path)) end - it { @blob_path.should be_allowed_for master } - it { @blob_path.should be_allowed_for reporter } - it { @blob_path.should be_allowed_for :admin } - it { @blob_path.should be_denied_for guest } - it { @blob_path.should be_denied_for :user } - it { @blob_path.should be_denied_for :visitor } + it { expect(@blob_path).to be_allowed_for master } + it { expect(@blob_path).to be_allowed_for reporter } + it { expect(@blob_path).to be_allowed_for :admin } + it { expect(@blob_path).to be_denied_for guest } + it { expect(@blob_path).to be_denied_for :user } + it { expect(@blob_path).to be_denied_for :visitor } end describe "GET /:project_path/edit" do - subject { edit_project_path(project) } + subject { edit_namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/deploy_keys" do - subject { project_deploy_keys_path(project) } + subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/issues" do - subject { project_issues_path(project) } + subject { namespace_project_issues_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/snippets" do - subject { project_snippets_path(project) } + subject { namespace_project_snippets_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/merge_requests" do - subject { project_merge_requests_path(project) } + subject { namespace_project_merge_requests_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/branches" do - subject { project_branches_path(project) } + subject { namespace_project_branches_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:branches).and_return([]) + allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/tags" do - subject { project_tags_path(project) } + subject { namespace_project_tags_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:tags).and_return([]) + allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/hooks" do - subject { project_hooks_path(project) } - - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + subject { namespace_project_hooks_path(project.namespace, project) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + 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 a4c8a2be25a..6ec190ed777 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -23,207 +23,210 @@ describe "Public Project Access", feature: true do describe "Project should be public" do subject { project } - its(:public?) { should be_true } + describe '#public?' do + subject { super().public? } + it { is_expected.to be_truthy } + end end describe "GET /:project_path" do - subject { project_path(project) } + subject { namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/tree/master" do - subject { project_tree_path(project, project.repository.root_ref) } + subject { namespace_project_tree_path(project.namespace, project, project.repository.root_ref) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/commits/master" do - subject { project_commits_path(project, project.repository.root_ref, limit: 1) } + subject { namespace_project_commits_path(project.namespace, project, project.repository.root_ref, limit: 1) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/commit/:sha" do - subject { project_commit_path(project, project.repository.commit) } + subject { namespace_project_commit_path(project.namespace, project, project.repository.commit) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/compare" do - subject { project_compare_index_path(project) } + subject { namespace_project_compare_index_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end - describe "GET /:project_path/team" do - subject { project_team_index_path(project) } + describe "GET /:project_path/project_members" do + subject { namespace_project_project_members_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/blob" do before do commit = project.repository.commit path = '.gitignore' - @blob_path = project_blob_path(project, File.join(commit.id, path)) + @blob_path = namespace_project_blob_path(project.namespace, project, File.join(commit.id, path)) end - it { @blob_path.should be_allowed_for master } - it { @blob_path.should be_allowed_for reporter } - it { @blob_path.should be_allowed_for :admin } - it { @blob_path.should be_allowed_for guest } - it { @blob_path.should be_allowed_for :user } - it { @blob_path.should be_allowed_for :visitor } + it { expect(@blob_path).to be_allowed_for master } + it { expect(@blob_path).to be_allowed_for reporter } + it { expect(@blob_path).to be_allowed_for :admin } + it { expect(@blob_path).to be_allowed_for guest } + it { expect(@blob_path).to be_allowed_for :user } + it { expect(@blob_path).to be_allowed_for :visitor } end describe "GET /:project_path/edit" do - subject { edit_project_path(project) } + subject { edit_namespace_project_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/deploy_keys" do - subject { project_deploy_keys_path(project) } + subject { namespace_project_deploy_keys_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/issues" do - subject { project_issues_path(project) } + subject { namespace_project_issues_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/snippets" do - subject { project_snippets_path(project) } + subject { namespace_project_snippets_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/snippets/new" do - subject { new_project_snippet_path(project) } + subject { new_namespace_project_snippet_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/merge_requests" do - subject { project_merge_requests_path(project) } + subject { namespace_project_merge_requests_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/merge_requests/new" do - subject { new_project_merge_request_path(project) } + subject { new_namespace_project_merge_request_path(project.namespace, project) } - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end describe "GET /:project_path/branches" do - subject { project_branches_path(project) } + subject { namespace_project_branches_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:branches).and_return([]) + allow_any_instance_of(Project).to receive(:branches).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/tags" do - subject { project_tags_path(project) } + subject { namespace_project_tags_path(project.namespace, project) } before do # Speed increase - Project.any_instance.stub(:tags).and_return([]) + allow_any_instance_of(Project).to receive(:tags).and_return([]) end - it { should be_allowed_for master } - it { should be_allowed_for reporter } - it { should be_allowed_for :admin } - it { should be_allowed_for guest } - it { should be_allowed_for :user } - it { should be_allowed_for :visitor } + it { is_expected.to be_allowed_for master } + it { is_expected.to be_allowed_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_allowed_for guest } + it { is_expected.to be_allowed_for :user } + it { is_expected.to be_allowed_for :visitor } end describe "GET /:project_path/hooks" do - subject { project_hooks_path(project) } - - it { should be_allowed_for master } - it { should be_denied_for reporter } - it { should be_allowed_for :admin } - it { should be_denied_for guest } - it { should be_denied_for :user } - it { should be_denied_for :visitor } + subject { namespace_project_hooks_path(project.namespace, project) } + + it { is_expected.to be_allowed_for master } + it { is_expected.to be_denied_for reporter } + it { is_expected.to be_allowed_for :admin } + it { is_expected.to be_denied_for guest } + it { is_expected.to be_denied_for :user } + it { is_expected.to be_denied_for :visitor } end end diff --git a/spec/features/users_spec.rb b/spec/features/users_spec.rb index 7b831c48611..21a3a4bf937 100644 --- a/spec/features/users_spec.rb +++ b/spec/features/users_spec.rb @@ -1,19 +1,14 @@ require 'spec_helper' describe 'Users', feature: true do - describe "GET /users/sign_up" do - before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) - end - + describe "GET /users/sign_in" do it "should create a new user account" do - visit new_user_registration_path + visit new_user_session_path fill_in "user_name", with: "Name Surname" fill_in "user_username", with: "Great" fill_in "user_email", with: "name@mail.com" - fill_in "user_password", with: "password1234" - fill_in "user_password_confirmation", with: "password1234" - expect { click_button "Sign up" }.to change {User.count}.by(1) + fill_in "user_password_sign_up", with: "password1234" + expect { click_button "Sign up" }.to change { User.count }.by(1) end end end diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb index 7489e56f423..479fa950387 100644 --- a/spec/finders/issues_finder_spec.rb +++ b/spec/finders/issues_finder_spec.rb @@ -5,9 +5,10 @@ describe IssuesFinder do let(:user2) { create :user } let(:project1) { create(:project) } let(:project2) { create(:project) } - let(:issue1) { create(:issue, assignee: user, project: project1) } - let(:issue2) { create(:issue, assignee: user, project: project2) } - let(:issue3) { create(:issue, assignee: user2, project: project2) } + let(:milestone) { create(:milestone, project: project1) } + let(:issue1) { create(:issue, author: user, assignee: user, project: project1, milestone: milestone) } + let(:issue2) { create(:issue, author: user, assignee: user, project: project2) } + let(:issue3) { create(:issue, author: user2, assignee: user2, project: project2) } before do project1.team << [user, :master] @@ -22,37 +23,59 @@ describe IssuesFinder do issue3 end - it 'should filter by all' do - params = { scope: "all", state: 'opened' } - issues = IssuesFinder.new.execute(user, params) - issues.size.should == 3 - end + context 'scope: all' do + it 'should filter by all' do + params = { scope: "all", state: 'opened' } + issues = IssuesFinder.new.execute(user, params) + expect(issues.size).to eq(3) + end - it 'should filter by assignee' do - params = { scope: "assigned-to-me", state: 'opened' } - issues = IssuesFinder.new.execute(user, params) - issues.size.should == 2 - end + it 'should filter by assignee id' do + params = { scope: "all", assignee_id: user.id, state: 'opened' } + issues = IssuesFinder.new.execute(user, params) + expect(issues.size).to eq(2) + end - it 'should filter by project' do - params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id } - issues = IssuesFinder.new.execute(user, params) - issues.size.should == 1 - end + it 'should filter by author id' do + params = { scope: "all", author_id: user2.id, state: 'opened' } + issues = IssuesFinder.new.execute(user, params) + expect(issues).to eq([issue3]) + end - it 'should be empty for unauthorized user' do - params = { scope: "all", state: 'opened' } - issues = IssuesFinder.new.execute(nil, params) - issues.size.should be_zero + it 'should filter by milestone id' do + params = { scope: "all", milestone_id: milestone.id, state: 'opened' } + issues = IssuesFinder.new.execute(user, params) + expect(issues).to eq([issue1]) + end + + it 'should be empty for unauthorized user' do + params = { scope: "all", state: 'opened' } + issues = IssuesFinder.new.execute(nil, params) + expect(issues.size).to be_zero + end + + it 'should not include unauthorized issues' do + params = { scope: "all", state: 'opened' } + issues = IssuesFinder.new.execute(user2, params) + expect(issues.size).to eq(2) + expect(issues).not_to include(issue1) + expect(issues).to include(issue2) + expect(issues).to include(issue3) + end end - it 'should not include unauthorized issues' do - params = { scope: "all", state: 'opened' } - issues = IssuesFinder.new.execute(user2, params) - issues.size.should == 2 - issues.should_not include(issue1) - issues.should include(issue2) - issues.should include(issue3) + context 'personal scope' do + it 'should filter by assignee' do + params = { scope: "assigned-to-me", state: 'opened' } + issues = IssuesFinder.new.execute(user, params) + expect(issues.size).to eq(2) + end + + it 'should filter by project' do + params = { scope: "assigned-to-me", state: 'opened', project_id: project1.id } + issues = IssuesFinder.new.execute(user, params) + expect(issues.size).to eq(1) + end end end end diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb index 94b4d4c4ff4..8536377a7f0 100644 --- a/spec/finders/merge_requests_finder_spec.rb +++ b/spec/finders/merge_requests_finder_spec.rb @@ -21,13 +21,13 @@ describe MergeRequestsFinder do it 'should filter by scope' do params = { scope: 'authored', state: 'opened' } merge_requests = MergeRequestsFinder.new.execute(user, params) - merge_requests.size.should == 2 + expect(merge_requests.size).to eq(2) end it 'should filter by project' do params = { project_id: project1.id, scope: 'authored', state: 'opened' } merge_requests = MergeRequestsFinder.new.execute(user, params) - merge_requests.size.should == 1 + expect(merge_requests.size).to eq(1) end end end diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb index 4f8a5f909df..c83824b900d 100644 --- a/spec/finders/notes_finder_spec.rb +++ b/spec/finders/notes_finder_spec.rb @@ -21,7 +21,7 @@ describe NotesFinder do it 'should find all notes' do notes = NotesFinder.new.execute(project, user, params) - notes.size.should eq(2) + expect(notes.size).to eq(2) end it 'should raise an exception for an invalid target_type' do @@ -32,7 +32,7 @@ describe NotesFinder do it 'filters out old notes' do note2.update_attribute(:updated_at, 2.hours.ago) notes = NotesFinder.new.execute(project, user, params) - notes.should eq([note1]) + expect(notes).to eq([note1]) end end end diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb index 6e3ae4d615b..2ab71b05968 100644 --- a/spec/finders/projects_finder_spec.rb +++ b/spec/finders/projects_finder_spec.rb @@ -12,19 +12,19 @@ describe ProjectsFinder do context 'non authenticated' do subject { ProjectsFinder.new.execute(nil, group: group) } - it { should include(project1) } - it { should_not include(project2) } - it { should_not include(project3) } - it { should_not include(project4) } + it { is_expected.to include(project1) } + it { is_expected.not_to include(project2) } + it { is_expected.not_to include(project3) } + it { is_expected.not_to include(project4) } end context 'authenticated' do subject { ProjectsFinder.new.execute(user, group: group) } - it { should include(project1) } - it { should include(project2) } - it { should_not include(project3) } - it { should_not include(project4) } + it { is_expected.to include(project1) } + it { is_expected.to include(project2) } + it { is_expected.not_to include(project3) } + it { is_expected.not_to include(project4) } end context 'authenticated, project member' do @@ -32,10 +32,10 @@ describe ProjectsFinder do subject { ProjectsFinder.new.execute(user, group: group) } - it { should include(project1) } - it { should include(project2) } - it { should include(project3) } - it { should_not include(project4) } + it { is_expected.to include(project1) } + it { is_expected.to include(project2) } + it { is_expected.to include(project3) } + it { is_expected.not_to include(project4) } end context 'authenticated, group member' do @@ -43,9 +43,9 @@ describe ProjectsFinder do subject { ProjectsFinder.new.execute(user, group: group) } - it { should include(project1) } - it { should include(project2) } - it { should include(project3) } - it { should include(project4) } + it { is_expected.to include(project1) } + it { is_expected.to include(project2) } + it { is_expected.to include(project3) } + it { is_expected.to include(project4) } end end diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb index 5af76968183..1b4ffc2d717 100644 --- a/spec/finders/snippets_finder_spec.rb +++ b/spec/finders/snippets_finder_spec.rb @@ -18,14 +18,14 @@ describe SnippetsFinder do it "returns all private and internal snippets" do snippets = SnippetsFinder.new.execute(user, filter: :all) - snippets.should include(@snippet2, @snippet3) - snippets.should_not include(@snippet1) + expect(snippets).to include(@snippet2, @snippet3) + expect(snippets).not_to include(@snippet1) end it "returns all public snippets" do snippets = SnippetsFinder.new.execute(nil, filter: :all) - snippets.should include(@snippet3) - snippets.should_not include(@snippet1, @snippet2) + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet1, @snippet2) end end @@ -38,32 +38,39 @@ describe SnippetsFinder do it "returns all public and internal snippets" do snippets = SnippetsFinder.new.execute(user1, filter: :by_user, user: user) - snippets.should include(@snippet2, @snippet3) - snippets.should_not include(@snippet1) + expect(snippets).to include(@snippet2, @snippet3) + expect(snippets).not_to include(@snippet1) end it "returns internal snippets" do snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_internal") - snippets.should include(@snippet2) - snippets.should_not include(@snippet1, @snippet3) + expect(snippets).to include(@snippet2) + expect(snippets).not_to include(@snippet1, @snippet3) end it "returns private snippets" do snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_private") - snippets.should include(@snippet1) - snippets.should_not include(@snippet2, @snippet3) + expect(snippets).to include(@snippet1) + expect(snippets).not_to include(@snippet2, @snippet3) end it "returns public snippets" do snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user, scope: "are_public") - snippets.should include(@snippet3) - snippets.should_not include(@snippet1, @snippet2) + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet1, @snippet2) end it "returns all snippets" do snippets = SnippetsFinder.new.execute(user, filter: :by_user, user: user) - snippets.should include(@snippet1, @snippet2, @snippet3) + expect(snippets).to include(@snippet1, @snippet2, @snippet3) end + + it "returns only public snippets if unauthenticated user" do + snippets = SnippetsFinder.new.execute(nil, filter: :by_user, user: user) + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet2, @snippet1) + end + end context 'by_project filter' do @@ -75,20 +82,20 @@ describe SnippetsFinder do it "returns public snippets for unauthorized user" do snippets = SnippetsFinder.new.execute(nil, filter: :by_project, project: project1) - snippets.should include(@snippet3) - snippets.should_not include(@snippet1, @snippet2) + expect(snippets).to include(@snippet3) + expect(snippets).not_to include(@snippet1, @snippet2) end it "returns public and internal snippets for none project members" do snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1) - snippets.should include(@snippet2, @snippet3) - snippets.should_not include(@snippet1) + expect(snippets).to include(@snippet2, @snippet3) + expect(snippets).not_to include(@snippet1) end it "returns all snippets for project members" do project1.team << [user, :developer] snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1) - snippets.should include(@snippet1, @snippet2, @snippet3) + expect(snippets).to include(@snippet1, @snippet2, @snippet3) end end end diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index 2db67cfdf95..4c11709ed6e 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -3,20 +3,20 @@ require 'spec_helper' describe ApplicationHelper do describe 'current_controller?' do before do - controller.stub(:controller_name).and_return('foo') + allow(controller).to receive(:controller_name).and_return('foo') end - it "returns true when controller matches argument" do - current_controller?(:foo).should be_true + it 'returns true when controller matches argument' do + expect(current_controller?(:foo)).to be_truthy end - it "returns false when controller does not match argument" do - current_controller?(:bar).should_not be_true + it 'returns false when controller does not match argument' do + expect(current_controller?(:bar)).not_to be_truthy end - it "should take any number of arguments" do - current_controller?(:baz, :bar).should_not be_true - current_controller?(:baz, :bar, :foo).should be_true + it 'should take any number of arguments' do + expect(current_controller?(:baz, :bar)).not_to be_truthy + expect(current_controller?(:baz, :bar, :foo)).to be_truthy end end @@ -25,99 +25,124 @@ describe ApplicationHelper do allow(self).to receive(:action_name).and_return('foo') end - it "returns true when action matches argument" do - current_action?(:foo).should be_true + it 'returns true when action matches argument' do + expect(current_action?(:foo)).to be_truthy end - it "returns false when action does not match argument" do - current_action?(:bar).should_not be_true + it 'returns false when action does not match argument' do + expect(current_action?(:bar)).not_to be_truthy end - it "should take any number of arguments" do - current_action?(:baz, :bar).should_not be_true - current_action?(:baz, :bar, :foo).should be_true + it 'should take any number of arguments' do + expect(current_action?(:baz, :bar)).not_to be_truthy + expect(current_action?(:baz, :bar, :foo)).to be_truthy end end - describe "group_icon" do + describe 'project_icon' do avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png') - it "should return an url for the avatar" do - group = create(:group) - group.avatar = File.open(avatar_file_path) - group.save! - group_icon(group.path).to_s.should match("/uploads/group/avatar/#{ group.id }/gitlab_logo.png") + it 'should return an url for the avatar' do + project = create(:project) + project.avatar = File.open(avatar_file_path) + project.save! + avatar_url = "http://localhost/uploads/project/avatar/#{ project.id }/gitlab_logo.png" + expect(project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).to eq( + "<img alt=\"Gitlab logo\" src=\"#{avatar_url}\" />" + ) end - it "should give default avatar_icon when no avatar is present" do - group = create(:group) - group.save! - group_icon(group.path).should match("group_avatar.png") + it 'should give uploaded icon when present' do + project = create(:project) + project.save! + + allow_any_instance_of(Project).to receive(:avatar_in_git).and_return(true) + + avatar_url = 'http://localhost' + namespace_project_avatar_path(project.namespace, project) + expect(project_icon("#{project.namespace.to_param}/#{project.to_param}").to_s).to match( + image_tag(avatar_url)) end end - describe "avatar_icon" do + describe 'avatar_icon' do avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png') - it "should return an url for the avatar" do + it 'should return an url for the avatar' do + user = create(:user) + user.avatar = File.open(avatar_file_path) + user.save! + expect(avatar_icon(user.email).to_s). + to match("/uploads/user/avatar/#{ user.id }/gitlab_logo.png") + end + + it 'should return an url for the avatar with relative url' do + Gitlab.config.gitlab.stub(relative_url_root: '/gitlab') + Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url)) + user = create(:user) user.avatar = File.open(avatar_file_path) user.save! - avatar_icon(user.email).to_s.should match("/uploads/user/avatar/#{ user.id }/gitlab_logo.png") + expect(avatar_icon(user.email).to_s). + to match("/gitlab/uploads/user/avatar/#{ user.id }/gitlab_logo.png") end - it "should call gravatar_icon when no avatar is present" do + it 'should call gravatar_icon when no avatar is present' do user = create(:user, email: 'test@example.com') user.save! - avatar_icon(user.email).to_s.should == "http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon" + expect(avatar_icon(user.email).to_s).to eq('http://www.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0?s=40&d=identicon') end end - describe "gravatar_icon" do + describe 'gravatar_icon' do let(:user_email) { 'user@email.com' } - it "should return a generic avatar path when Gravatar is disabled" do - Gitlab.config.gravatar.stub(:enabled).and_return(false) - gravatar_icon(user_email).should match('no_avatar.png') + it 'should return a generic avatar path when Gravatar is disabled' do + ApplicationSetting.any_instance.stub(gravatar_enabled?: false) + expect(gravatar_icon(user_email)).to match('no_avatar.png') end - it "should return a generic avatar path when email is blank" do - gravatar_icon('').should match('no_avatar.png') + it 'should return a generic avatar path when email is blank' do + expect(gravatar_icon('')).to match('no_avatar.png') end - it "should return default gravatar url" do + it 'should return default gravatar url' do Gitlab.config.gitlab.stub(https: false) - gravatar_icon(user_email).should match('http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118') + url = 'http://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118' + expect(gravatar_icon(user_email)).to match(url) end - it "should use SSL when appropriate" do + it 'should use SSL when appropriate' do Gitlab.config.gitlab.stub(https: true) - gravatar_icon(user_email).should match('https://secure.gravatar.com') + expect(gravatar_icon(user_email)).to match('https://secure.gravatar.com') end - it "should return custom gravatar path when gravatar_url is set" do + it 'should return custom gravatar path when gravatar_url is set' do allow(self).to receive(:request).and_return(double(:ssl? => false)) - Gitlab.config.gravatar.stub(:plain_url).and_return('http://example.local/?s=%{size}&hash=%{hash}') - gravatar_icon(user_email, 20).should == 'http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118' + allow(Gitlab.config.gravatar). + to receive(:plain_url). + and_return('http://example.local/?s=%{size}&hash=%{hash}') + url = 'http://example.local/?s=20&hash=b58c6f14d292556214bd64909bcdb118' + expect(gravatar_icon(user_email, 20)).to eq(url) end - it "should accept a custom size" do + it 'should accept a custom size' do allow(self).to receive(:request).and_return(double(:ssl? => false)) - gravatar_icon(user_email, 64).should match(/\?s=64/) + expect(gravatar_icon(user_email, 64)).to match(/\?s=64/) end - it "should use default size when size is wrong" do + it 'should use default size when size is wrong' do allow(self).to receive(:request).and_return(double(:ssl? => false)) - gravatar_icon(user_email, nil).should match(/\?s=40/) + expect(gravatar_icon(user_email, nil)).to match(/\?s=40/) end - it "should be case insensitive" do + it 'should be case insensitive' do allow(self).to receive(:request).and_return(double(:ssl? => false)) - gravatar_icon(user_email).should == gravatar_icon(user_email.upcase + " ") + expect(gravatar_icon(user_email)). + to eq(gravatar_icon(user_email.upcase + ' ')) end end - describe "grouped_options_refs" do + describe 'grouped_options_refs' do # Override Rails' grouped_options_for_select helper since HTML is harder to work with def grouped_options_for_select(options, *args) options @@ -130,90 +155,94 @@ describe ApplicationHelper do @project = create(:project) end - it "includes a list of branch names" do - options[0][0].should == 'Branches' - options[0][1].should include('master', 'feature') + it 'includes a list of branch names' do + expect(options[0][0]).to eq('Branches') + expect(options[0][1]).to include('master', 'feature') end - it "includes a list of tag names" do - options[1][0].should == 'Tags' - options[1][1].should include('v1.0.0','v1.1.0') + it 'includes a list of tag names' do + expect(options[1][0]).to eq('Tags') + expect(options[1][1]).to include('v1.0.0', 'v1.1.0') end - it "includes a specific commit ref if defined" do + it 'includes a specific commit ref if defined' do # Must be an instance variable @ref = '2ed06dc41dbb5936af845b87d79e05bbf24c73b8' - options[2][0].should == 'Commit' - options[2][1].should == [@ref] + expect(options[2][0]).to eq('Commit') + expect(options[2][1]).to eq([@ref]) end - it "sorts tags in a natural order" do + it 'sorts tags in a natural order' do # Stub repository.tag_names to make sure we get some valid testing data - expect(@project.repository).to receive(:tag_names).and_return(["v1.0.9", "v1.0.10", "v2.0", "v3.1.4.2", "v1.0.9a"]) + expect(@project.repository).to receive(:tag_names). + and_return(['v1.0.9', 'v1.0.10', 'v2.0', 'v3.1.4.2', 'v2.0rc1¿', + 'v1.0.9a', 'v2.0-rc1', 'v2.0rc2']) - options[1][1].should == ["v3.1.4.2", "v2.0", "v1.0.10", "v1.0.9a", "v1.0.9"] + expect(options[1][1]). + to eq(['v3.1.4.2', 'v2.0', 'v2.0rc2', 'v2.0rc1¿', 'v2.0-rc1', 'v1.0.10', + 'v1.0.9', 'v1.0.9a']) end end - describe "user_color_scheme_class" do - context "with current_user is nil" do - it "should return a string" do + describe 'user_color_scheme_class' do + context 'with current_user is nil' do + it 'should return a string' do allow(self).to receive(:current_user).and_return(nil) - user_color_scheme_class.should be_kind_of(String) + expect(user_color_scheme_class).to be_kind_of(String) end end - context "with a current_user" do + context 'with a current_user' do (1..5).each do |color_scheme_id| context "with color_scheme_id == #{color_scheme_id}" do - it "should return a string" do + it 'should return a string' do current_user = double(:color_scheme_id => color_scheme_id) allow(self).to receive(:current_user).and_return(current_user) - user_color_scheme_class.should be_kind_of(String) + expect(user_color_scheme_class).to be_kind_of(String) end end end end end - describe "simple_sanitize" do + describe 'simple_sanitize' do let(:a_tag) { '<a href="#">Foo</a>' } - it "allows the a tag" do - simple_sanitize(a_tag).should == a_tag + it 'allows the a tag' do + expect(simple_sanitize(a_tag)).to eq(a_tag) end - it "allows the span tag" do + it 'allows the span tag' do input = '<span class="foo">Bar</span>' - simple_sanitize(input).should == input + expect(simple_sanitize(input)).to eq(input) end - it "disallows other tags" do + it 'disallows other tags' do input = "<strike><b>#{a_tag}</b></strike>" - simple_sanitize(input).should == a_tag + expect(simple_sanitize(input)).to eq(a_tag) end end - describe "link_to" do + describe 'link_to' do - it "should not include rel=nofollow for internal links" do - expect(link_to("Home", root_path)).to eq("<a href=\"/\">Home</a>") + it 'should not include rel=nofollow for internal links' do + expect(link_to('Home', root_path)).to eq("<a href=\"/\">Home</a>") end - it "should include rel=nofollow for external links" do - expect(link_to("Example", "http://www.example.com")).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>") + it 'should include rel=nofollow for external links' do + expect(link_to('Example', 'http://www.example.com')).to eq("<a href=\"http://www.example.com\" rel=\"nofollow\">Example</a>") end - it "should include re=nofollow for external links and honor existing html_options" do + it 'should include re=nofollow for external links and honor existing html_options' do expect( - link_to("Example", "http://www.example.com", class: "toggle", data: {toggle: "dropdown"}) + link_to('Example', 'http://www.example.com', class: 'toggle', data: {toggle: 'dropdown'}) ).to eq("<a class=\"toggle\" data-toggle=\"dropdown\" href=\"http://www.example.com\" rel=\"nofollow\">Example</a>") end - it "should include rel=nofollow for external links and preserver other rel values" do + it 'should include rel=nofollow for external links and preserver other rel values' do expect( - link_to("Example", "http://www.example.com", rel: "noreferrer") + link_to('Example', 'http://www.example.com', rel: 'noreferrer') ).to eq("<a href=\"http://www.example.com\" rel=\"noreferrer nofollow\">Example</a>") end end @@ -222,7 +251,7 @@ describe ApplicationHelper do let(:content) { 'Noël' } it 'should preserve encoding' do - content.encoding.name.should == 'UTF-8' + expect(content.encoding.name).to eq('UTF-8') expect(render_markup('foo.rst', content).encoding.name).to eq('UTF-8') end end diff --git a/spec/helpers/broadcast_messages_helper_spec.rb b/spec/helpers/broadcast_messages_helper_spec.rb index 1338ce4873d..f6df12662bb 100644 --- a/spec/helpers/broadcast_messages_helper_spec.rb +++ b/spec/helpers/broadcast_messages_helper_spec.rb @@ -6,7 +6,7 @@ describe BroadcastMessagesHelper do context "default style" do it "should have no style" do - broadcast_styling(broadcast_message).should match('') + expect(broadcast_styling(broadcast_message)).to match('') end end @@ -14,7 +14,8 @@ describe BroadcastMessagesHelper do before { broadcast_message.stub(color: "#f2dede", font: "#b94a48") } it "should have a customized style" do - broadcast_styling(broadcast_message).should match('background-color:#f2dede;color:#b94a48') + expect(broadcast_styling(broadcast_message)). + to match('background-color:#f2dede;color:#b94a48') end end end diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb index b07742a6ee2..5bd09793b11 100644 --- a/spec/helpers/diff_helper_spec.rb +++ b/spec/helpers/diff_helper_spec.rb @@ -10,58 +10,61 @@ describe DiffHelper do describe 'diff_hard_limit_enabled?' do it 'should return true if param is provided' do - controller.stub(:params).and_return { { :force_show_diff => true } } - diff_hard_limit_enabled?.should be_true + allow(controller).to receive(:params) { { force_show_diff: true } } + expect(diff_hard_limit_enabled?).to be_truthy end it 'should return false if param is not provided' do - diff_hard_limit_enabled?.should be_false + expect(diff_hard_limit_enabled?).to be_falsey end end describe 'allowed_diff_size' do it 'should return hard limit for a diff if force diff is true' do - controller.stub(:params).and_return { { :force_show_diff => true } } - allowed_diff_size.should eq(1000) + allow(controller).to receive(:params) { { force_show_diff: true } } + expect(allowed_diff_size).to eq(1000) end it 'should return safe limit for a diff if force diff is false' do - allowed_diff_size.should eq(100) + expect(allowed_diff_size).to eq(100) end end describe 'parallel_diff' do it 'should return an array of arrays containing the parsed diff' do - parallel_diff(diff_file, 0).should match_array(parallel_diff_result_array) + expect(parallel_diff(diff_file, 0)). + to match_array(parallel_diff_result_array) end end describe 'generate_line_code' do it 'should generate correct line code' do - generate_line_code(diff_file.file_path, diff_file.diff_lines.first).should == '2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6' + expect(generate_line_code(diff_file.file_path, diff_file.diff_lines.first)). + to eq('2f6fcd96b88b36ce98c38da085c795a27d92a3dd_6_6') end end describe 'unfold_bottom_class' do it 'should return empty string when bottom line shouldnt be unfolded' do - unfold_bottom_class(false).should == '' + expect(unfold_bottom_class(false)).to eq('') end it 'should return js class when bottom lines should be unfolded' do - unfold_bottom_class(true).should == 'js-unfold-bottom' + expect(unfold_bottom_class(true)).to eq('js-unfold-bottom') end end describe 'diff_line_content' do it 'should return non breaking space when line is empty' do - diff_line_content(nil).should eq(" ") + expect(diff_line_content(nil)).to eq(' ') end it 'should return the line itself' do - diff_line_content(diff_file.diff_lines.first.text).should eq("@@ -6,12 +6,18 @@ module Popen") - diff_line_content(diff_file.diff_lines.first.type).should eq("match") - diff_line_content(diff_file.diff_lines.first.new_pos).should eq(6) + expect(diff_line_content(diff_file.diff_lines.first.text)). + to eq('@@ -6,12 +6,18 @@ module Popen') + expect(diff_line_content(diff_file.diff_lines.first.type)).to eq('match') + expect(diff_line_content(diff_file.diff_lines.first.new_pos)).to eq(6) end end diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb new file mode 100644 index 00000000000..b392371deb4 --- /dev/null +++ b/spec/helpers/events_helper_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe EventsHelper do + include ApplicationHelper + include GitlabMarkdownHelper + + let(:current_user) { create(:user, email: "current@email.com") } + + it 'should display one line of plain text without alteration' do + input = 'A short, plain note' + expect(event_note(input)).to match(input) + expect(event_note(input)).not_to match(/\.\.\.\z/) + end + + it 'should display inline code' do + input = 'A note with `inline code`' + expected = 'A note with <code>inline code</code>' + + expect(event_note(input)).to match(expected) + end + + it 'should truncate a note with multiple paragraphs' do + input = "Paragraph 1\n\nParagraph 2" + expected = 'Paragraph 1...' + + expect(event_note(input)).to match(expected) + end + + it 'should display the first line of a code block' do + input = "```\nCode block\nwith two lines\n```" + expected = '<pre class="code highlight white plaintext"><code>' \ + 'Code block...</code></pre>' + + expect(event_note(input)).to match(expected) + end + + it 'should truncate a single long line of text' do + text = 'The quick brown fox jumped over the lazy dog twice' # 50 chars + input = "#{text}#{text}#{text}#{text}" # 200 chars + expected = "#{text}#{text}".sub(/.{3}/, '...') + + expect(event_note(input)).to match(expected) + end + + it 'should preserve a link href when link text is truncated' do + text = 'The quick brown fox jumped over the lazy dog' # 44 chars + input = "#{text}#{text}#{text} " # 133 chars + link_url = 'http://example.com/foo/bar/baz' # 30 chars + input << link_url + expected_link_text = 'http://example...</a>' + + expect(event_note(input)).to match(link_url) + expect(event_note(input)).to match(expected_link_text) + end + + it 'should preserve code color scheme' do + input = "```ruby\ndef test\n 'hello world'\nend\n```" + expected = '<pre class="code highlight white ruby">' \ + "<code><span class=\"k\">def</span> <span class=\"nf\">test</span>\n" \ + " <span class=\"s1\">\'hello world\'</span>\n" \ + "<span class=\"k\">end</span>\n" \ + '</code></pre>' + expect(event_note(input)).to eq(expected) + end +end diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb index c75773ad321..3a884d39bf1 100644 --- a/spec/helpers/gitlab_markdown_helper_spec.rb +++ b/spec/helpers/gitlab_markdown_helper_spec.rb @@ -1,4 +1,4 @@ -require "spec_helper" +require 'spec_helper' describe GitlabMarkdownHelper do include ApplicationHelper @@ -9,6 +9,7 @@ describe GitlabMarkdownHelper do let(:user) { create(:user, username: 'gfm') } let(:commit) { project.repository.commit } + let(:earlier_commit){ project.repository.commit("HEAD~2") } let(:issue) { create(:issue, project: project) } let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } let(:snippet) { create(:project_snippet, project: project) } @@ -23,71 +24,120 @@ describe GitlabMarkdownHelper do @project = project @ref = 'markdown' @repository = project.repository + @request.host = Gitlab.config.gitlab.host end describe "#gfm" do it "should return unaltered text if project is nil" do actual = "Testing references: ##{issue.iid}" - gfm(actual).should_not == actual + expect(gfm(actual)).not_to eq(actual) @project = nil - gfm(actual).should == actual + expect(gfm(actual)).to eq(actual) end it "should not alter non-references" do actual = expected = "_Please_ *stop* 'helping' and all the other b*$#%' you do." - gfm(actual).should == expected + expect(gfm(actual)).to eq(expected) end it "should not touch HTML entities" do - @project.issues.stub(:where).with(id: '39').and_return([issue]) + allow(@project.issues).to receive(:where). + with(id: '39').and_return([issue]) actual = 'We'll accept good pull requests.' - gfm(actual).should == "We'll accept good pull requests." + expect(gfm(actual)).to eq("We'll accept good pull requests.") end it "should forward HTML options to links" do - gfm("Fixed in #{commit.id}", @project, class: 'foo'). - should have_selector('a.gfm.foo') + expect(gfm("Fixed in #{commit.id}", @project, class: 'foo')). + to have_selector('a.gfm.foo') + end + + describe "referencing a commit range" do + let(:expected) { namespace_project_compare_path(project.namespace, project, from: earlier_commit.id, to: commit.id) } + + it "should link using a full id" do + actual = "What happened in #{earlier_commit.id}...#{commit.id}" + expect(gfm(actual)).to match(expected) + end + + it "should link using a short id" do + actual = "What happened in #{earlier_commit.short_id}...#{commit.short_id}" + expected = namespace_project_compare_path(project.namespace, project, from: earlier_commit.short_id, to: commit.short_id) + expect(gfm(actual)).to match(expected) + end + + it "should link inclusively" do + actual = "What happened in #{earlier_commit.id}..#{commit.id}" + expected = namespace_project_compare_path(project.namespace, project, from: "#{earlier_commit.id}^", to: commit.id) + expect(gfm(actual)).to match(expected) + end + + it "should link with adjacent text" do + actual = "(see #{earlier_commit.id}...#{commit.id})" + expect(gfm(actual)).to match(expected) + end + + it "should keep whitespace intact" do + actual = "Changes #{earlier_commit.id}...#{commit.id} dramatically" + expected = /Changes <a.+>#{earlier_commit.id}...#{commit.id}<\/a> dramatically/ + expect(gfm(actual)).to match(expected) + end + + it "should not link with an invalid id" do + actual = expected = "What happened in #{earlier_commit.id.reverse}...#{commit.id.reverse}" + expect(gfm(actual)).to eq(expected) + end + + it "should include a title attribute" do + actual = "What happened in #{earlier_commit.id}...#{commit.id}" + expect(gfm(actual)).to match(/title="Commits #{earlier_commit.id} through #{commit.id}"/) + end + + it "should include standard gfm classes" do + actual = "What happened in #{earlier_commit.id}...#{commit.id}" + expect(gfm(actual)).to match(/class="\s?gfm gfm-commit_range\s?"/) + end end describe "referencing a commit" do - let(:expected) { project_commit_path(project, commit) } + let(:expected) { namespace_project_commit_path(project.namespace, project, commit) } it "should link using a full id" do actual = "Reverts #{commit.id}" - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link using a short id" do - actual = "Backported from #{commit.short_id(6)}" - gfm(actual).should match(expected) + actual = "Backported from #{commit.short_id}" + expect(gfm(actual)).to match(expected) end it "should link with adjacent text" do actual = "Reverted (see #{commit.id})" - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should keep whitespace intact" do actual = "Changes #{commit.id} dramatically" expected = /Changes <a.+>#{commit.id}<\/a> dramatically/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should not link with an invalid id" do actual = expected = "What happened in #{commit.id.reverse}" - gfm(actual).should == expected + expect(gfm(actual)).to eq(expected) end it "should include a title attribute" do actual = "Reverts #{commit.id}" - gfm(actual).should match(/title="#{commit.link_title}"/) + expect(gfm(actual)).to match(/title="#{commit.link_title}"/) end it "should include standard gfm classes" do actual = "Reverts #{commit.id}" - gfm(actual).should match(/class="\s?gfm gfm-commit\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-commit\s?"/) end end @@ -100,37 +150,37 @@ describe GitlabMarkdownHelper do end it "should link using a simple name" do - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link using a name with dots" do user.update_attributes(name: "alphA.Beta") - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link using name with underscores" do user.update_attributes(name: "ping_pong_king") - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link with adjacent text" do actual = "Mail the admin (@#{user.username})" - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should keep whitespace intact" do actual = "Yes, @#{user.username} is right." expected = /Yes, <a.+>@#{user.username}<\/a> is right/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should not link with an invalid id" do actual = expected = "@#{user.username.reverse} you are right." - gfm(actual).should == expected + expect(gfm(actual)).to eq(expected) end it "should include standard gfm classes" do - gfm(actual).should match(/class="\s?gfm gfm-team_member\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-project_member\s?"/) end end @@ -144,40 +194,41 @@ describe GitlabMarkdownHelper do # Currently limited to Snippets, Issues and MergeRequests shared_examples 'referenced object' do let(:actual) { "Reference to #{reference}" } - let(:expected) { polymorphic_path([project, object]) } + let(:expected) { polymorphic_path([project.namespace, project, object]) } it "should link using a valid id" do - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link with adjacent text" do # Wrap the reference in parenthesis - gfm(actual.gsub(reference, "(#{reference})")).should match(expected) + expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected) # Append some text to the end of the reference - gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected) + expect(gfm(actual.gsub(reference, "#{reference}, right?"))). + to match(expected) end it "should keep whitespace intact" do actual = "Referenced #{reference} already." expected = /Referenced <a.+>[^\s]+<\/a> already/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should not link with an invalid id" do # Modify the reference string so it's still parsed, but is invalid reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2)) - gfm(actual).should == actual + expect(gfm(actual)).to eq(actual) end it "should include a title attribute" do title = "#{object.class.to_s.titlecase}: #{object.title}" - gfm(actual).should match(/title="#{title}"/) + expect(gfm(actual)).to match(/title="#{title}"/) end it "should include standard gfm classes" do css = object.class.to_s.underscore - gfm(actual).should match(/class="\s?gfm gfm-#{css}\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-#{css}\s?"/) end end @@ -196,34 +247,33 @@ describe GitlabMarkdownHelper do let(:actual) { "Reference to #{full_reference}" } let(:expected) do if object.is_a?(Commit) - project_commit_path(@other_project, object) + namespace_project_commit_path(@other_project.namespace, @other_project, object) else - polymorphic_path([@other_project, object]) + polymorphic_path([@other_project.namespace, @other_project, object]) end end it 'should link using a valid id' do - gfm(actual).should match( + expect(gfm(actual)).to match( /#{expected}.*#{Regexp.escape(full_reference)}/ ) end it 'should link with adjacent text' do # Wrap the reference in parenthesis - gfm(actual.gsub(full_reference, "(#{full_reference})")).should( + expect(gfm(actual.gsub(full_reference, "(#{full_reference})"))).to( match(expected) ) # Append some text to the end of the reference - gfm(actual.gsub(full_reference, "#{full_reference}, right?")).should( - match(expected) - ) + expect(gfm(actual.gsub(full_reference, "#{full_reference}, right?"))). + to(match(expected)) end it 'should keep whitespace intact' do actual = "Referenced #{full_reference} already." expected = /Referenced <a.+>[^\s]+<\/a> already/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it 'should not link with an invalid id' do @@ -233,7 +283,7 @@ describe GitlabMarkdownHelper do else reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2)) end - gfm(actual).should == actual + expect(gfm(actual)).to eq(actual) end it 'should include a title attribute' do @@ -242,12 +292,12 @@ describe GitlabMarkdownHelper do else title = "#{object.class.to_s.titlecase}: #{object.title}" end - gfm(actual).should match(/title="#{title}"/) + expect(gfm(actual)).to match(/title="#{title}"/) end it 'should include standard gfm classes' do css = object.class.to_s.underscore - gfm(actual).should match(/class="\s?gfm gfm-#{css}\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-#{css}\s?"/) end end @@ -296,43 +346,47 @@ describe GitlabMarkdownHelper do let(:reference) { "JIRA-#{issue.iid}" } before do - issue_tracker_config = { "jira" => { "title" => "JIRA tracker", "issues_url" => "http://jira.example/browse/:id" } } - Gitlab.config.stub(:issues_tracker).and_return(issue_tracker_config) - @project.stub(:issues_tracker).and_return("jira") - @project.stub(:issues_tracker_id).and_return("JIRA") + jira = @project.create_jira_service if @project.jira_service.nil? + properties = {"title"=>"JIRA tracker", "project_url"=>"http://jira.example/issues/?jql=project=A", "issues_url"=>"http://jira.example/browse/:id", "new_issue_url"=>"http://jira.example/secure/CreateIssue.jspa"} + jira.update_attributes(properties: properties, active: true) + end + + after do + @project.jira_service.destroy! unless @project.jira_service.nil? end it "should link using a valid id" do - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link with adjacent text" do # Wrap the reference in parenthesis - gfm(actual.gsub(reference, "(#{reference})")).should match(expected) + expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected) # Append some text to the end of the reference - gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected) + expect(gfm(actual.gsub(reference, "#{reference}, right?"))). + to match(expected) end it "should keep whitespace intact" do actual = "Referenced #{reference} already." expected = /Referenced <a.+>[^\s]+<\/a> already/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should not link with an invalid id" do # Modify the reference string so it's still parsed, but is invalid invalid_reference = actual.gsub(/(\d+)$/, "r45") - gfm(invalid_reference).should == invalid_reference + expect(gfm(invalid_reference)).to eq(invalid_reference) end it "should include a title attribute" do title = "Issue in JIRA tracker" - gfm(actual).should match(/title="#{title}"/) + expect(gfm(actual)).to match(/title="#{title}"/) end it "should include standard gfm classes" do - gfm(actual).should match(/class="\s?gfm gfm-issue\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-issue\s?"/) end end @@ -347,40 +401,40 @@ describe GitlabMarkdownHelper do let(:object) { snippet } let(:reference) { "$#{snippet.id}" } let(:actual) { "Reference to #{reference}" } - let(:expected) { project_snippet_path(project, object) } + let(:expected) { namespace_project_snippet_path(project.namespace, project, object) } it "should link using a valid id" do - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should link with adjacent text" do # Wrap the reference in parenthesis - gfm(actual.gsub(reference, "(#{reference})")).should match(expected) + expect(gfm(actual.gsub(reference, "(#{reference})"))).to match(expected) # Append some text to the end of the reference - gfm(actual.gsub(reference, "#{reference}, right?")).should match(expected) + expect(gfm(actual.gsub(reference, "#{reference}, right?"))).to match(expected) end it "should keep whitespace intact" do actual = "Referenced #{reference} already." expected = /Referenced <a.+>[^\s]+<\/a> already/ - gfm(actual).should match(expected) + expect(gfm(actual)).to match(expected) end it "should not link with an invalid id" do # Modify the reference string so it's still parsed, but is invalid reference.gsub!(/^(.)(\d+)$/, '\1' + ('\2' * 2)) - gfm(actual).should == actual + expect(gfm(actual)).to eq(actual) end it "should include a title attribute" do title = "Snippet: #{object.title}" - gfm(actual).should match(/title="#{title}"/) + expect(gfm(actual)).to match(/title="#{title}"/) end it "should include standard gfm classes" do css = object.class.to_s.underscore - gfm(actual).should match(/class="\s?gfm gfm-snippet\s?"/) + expect(gfm(actual)).to match(/class="\s?gfm gfm-snippet\s?"/) end end @@ -389,70 +443,70 @@ describe GitlabMarkdownHelper do let(:actual) { "!#{merge_request.iid} -> #{commit.id} -> ##{issue.iid}" } it "should link to the merge request" do - expected = project_merge_request_path(project, merge_request) - gfm(actual).should match(expected) + expected = namespace_project_merge_request_path(project.namespace, project, merge_request) + expect(gfm(actual)).to match(expected) end it "should link to the commit" do - expected = project_commit_path(project, commit) - gfm(actual).should match(expected) + expected = namespace_project_commit_path(project.namespace, project, commit) + expect(gfm(actual)).to match(expected) end it "should link to the issue" do - expected = project_issue_path(project, issue) - gfm(actual).should match(expected) + expected = namespace_project_issue_path(project.namespace, project, issue) + expect(gfm(actual)).to match(expected) end end describe "emoji" do it "matches at the start of a string" do - gfm(":+1:").should match(/<img/) + expect(gfm(":+1:")).to match(/<img/) end it "matches at the end of a string" do - gfm("This gets a :-1:").should match(/<img/) + expect(gfm("This gets a :-1:")).to match(/<img/) end it "matches with adjacent text" do - gfm("+1 (:+1:)").should match(/<img/) + expect(gfm("+1 (:+1:)")).to match(/<img/) end it "has a title attribute" do - gfm(":-1:").should match(/title=":-1:"/) + expect(gfm(":-1:")).to match(/title=":-1:"/) end it "has an alt attribute" do - gfm(":-1:").should match(/alt=":-1:"/) + expect(gfm(":-1:")).to match(/alt=":-1:"/) end it "has an emoji class" do - gfm(":+1:").should match('class="emoji"') + expect(gfm(":+1:")).to match('class="emoji"') end it "sets height and width" do actual = gfm(":+1:") - actual.should match(/width="20"/) - actual.should match(/height="20"/) + expect(actual).to match(/width="20"/) + expect(actual).to match(/height="20"/) end it "keeps whitespace intact" do - gfm('This deserves a :+1: big time.'). - should match(/deserves a <img.+> big time/) + expect(gfm('This deserves a :+1: big time.')). + to match(/deserves a <img.+> big time/) end it "ignores invalid emoji" do - gfm(":invalid-emoji:").should_not match(/<img/) + expect(gfm(":invalid-emoji:")).not_to match(/<img/) end it "should work independent of reference links (i.e. without @project being set)" do @project = nil - gfm(":+1:").should match(/<img/) + expect(gfm(":+1:")).to match(/<img/) end end end describe "#link_to_gfm" do - let(:commit_path) { project_commit_path(project, commit) } + let(:commit_path) { namespace_project_commit_path(project.namespace, project, commit) } let(:issues) { create_list(:issue, 2, project: project) } it "should handle references nested in links with all the text" do @@ -463,60 +517,67 @@ describe GitlabMarkdownHelper do groups = actual.split("</a>") # Leading commit link - groups[0].should match(/href="#{commit_path}"/) - groups[0].should match(/This should finally fix $/) + expect(groups[0]).to match(/href="#{commit_path}"/) + expect(groups[0]).to match(/This should finally fix $/) # First issue link - groups[1].should match(/href="#{project_issue_url(project, issues[0])}"/) - groups[1].should match(/##{issues[0].iid}$/) + expect(groups[1]). + to match(/href="#{namespace_project_issue_path(project.namespace, project, issues[0])}"/) + expect(groups[1]).to match(/##{issues[0].iid}$/) # Internal commit link - groups[2].should match(/href="#{commit_path}"/) - groups[2].should match(/ and /) + expect(groups[2]).to match(/href="#{commit_path}"/) + expect(groups[2]).to match(/ and /) # Second issue link - groups[3].should match(/href="#{project_issue_url(project, issues[1])}"/) - groups[3].should match(/##{issues[1].iid}$/) + expect(groups[3]). + to match(/href="#{namespace_project_issue_path(project.namespace, project, issues[1])}"/) + expect(groups[3]).to match(/##{issues[1].iid}$/) # Trailing commit link - groups[4].should match(/href="#{commit_path}"/) - groups[4].should match(/ for real$/) + expect(groups[4]).to match(/href="#{commit_path}"/) + expect(groups[4]).to match(/ for real$/) end it "should forward HTML options" do actual = link_to_gfm("Fixed in #{commit.id}", commit_path, class: 'foo') - actual.should have_selector 'a.gfm.gfm-commit.foo' + expect(actual).to have_selector 'a.gfm.gfm-commit.foo' end it "escapes HTML passed in as the body" do actual = "This is a <h1>test</h1> - see ##{issues[0].iid}" - link_to_gfm(actual, commit_path).should match('<h1>test</h1>') + expect(link_to_gfm(actual, commit_path)). + to match('<h1>test</h1>') end end describe "#markdown" do it "should handle references in paragraphs" do actual = "\n\nLorem ipsum dolor sit amet. #{commit.id} Nam pulvinar sapien eget.\n" - expected = project_commit_path(project, commit) - markdown(actual).should match(expected) + expected = namespace_project_commit_path(project.namespace, project, commit) + expect(markdown(actual)).to match(expected) end it "should handle references in headers" do actual = "\n# Working around ##{issue.iid}\n## Apply !#{merge_request.iid}" - markdown(actual, {no_header_anchors:true}).should match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>}) - markdown(actual, {no_header_anchors:true}).should match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>}) + expect(markdown(actual, no_header_anchors: true)). + to match(%r{<h1[^<]*>Working around <a.+>##{issue.iid}</a></h1>}) + expect(markdown(actual, no_header_anchors: true)). + to match(%r{<h2[^<]*>Apply <a.+>!#{merge_request.iid}</a></h2>}) end it "should add ids and links to headers" do # Test every rule except nested tags. text = '..Ab_c-d. e..' id = 'ab_c-d-e' - markdown("# #{text}").should match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>}) - markdown("# #{text}", {no_header_anchors:true}).should == "<h1>#{text}</h1>" + expect(markdown("# #{text}")). + to match(%r{<h1 id="#{id}">#{text}<a href="[^"]*##{id}"></a></h1>}) + expect(markdown("# #{text}", {no_header_anchors:true})). + to eq("<h1>#{text}</h1>") id = 'link-text' - markdown("# [link text](url) ![img alt](url)").should match( + expect(markdown("# [link text](url) ![img alt](url)")).to match( %r{<h1 id="#{id}"><a href="[^"]*url">link text</a> <img[^>]*><a href="[^"]*##{id}"></a></h1>} ) end @@ -526,14 +587,37 @@ describe GitlabMarkdownHelper do actual = "\n* dark: ##{issue.iid}\n* light by @#{member.user.username}" - markdown(actual).should match(%r{<li>dark: <a.+>##{issue.iid}</a></li>}) - markdown(actual).should match(%r{<li>light by <a.+>@#{member.user.username}</a></li>}) + expect(markdown(actual)). + to match(%r{<li>dark: <a.+>##{issue.iid}</a></li>}) + expect(markdown(actual)). + to match(%r{<li>light by <a.+>@#{member.user.username}</a></li>}) + end + + it "should not link the apostrophe to issue 39" do + project.team << [user, :master] + allow(project.issues). + to receive(:where).with(iid: '39').and_return([issue]) + + actual = "Yes, it is @#{member.user.username}'s task." + expected = /Yes, it is <a.+>@#{member.user.username}<\/a>'s task/ + expect(markdown(actual)).to match(expected) + end + + it "should not link the apostrophe to issue 39 in code blocks" do + project.team << [user, :master] + allow(project.issues). + to receive(:where).with(iid: '39').and_return([issue]) + + actual = "Yes, `it is @#{member.user.username}'s task.`" + expected = /Yes, <code>it is @gfm\'s task.<\/code>/ + expect(markdown(actual)).to match(expected) end it "should handle references in <em>" do actual = "Apply _!#{merge_request.iid}_ ASAP" - markdown(actual).should match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>}) + expect(markdown(actual)). + to match(%r{Apply <em><a.+>!#{merge_request.iid}</a></em>}) end it "should handle tables" do @@ -542,77 +626,106 @@ describe GitlabMarkdownHelper do | cell 1 | cell 2 | | cell 3 | cell 4 |} - markdown(actual).should match(/\A<table/) + expect(markdown(actual)).to match(/\A<table/) end it "should leave code blocks untouched" do - helper.stub(:user_color_scheme_class).and_return(:white) + allow(helper).to receive(:user_color_scheme_class).and_return(:white) - target_html = "\n<div class=\"highlighted-data white\">\n <div class=\"highlight\">\n <pre><code class=\"\">some code from $#{snippet.id}\nhere too\n</code></pre>\n </div>\n</div>\n\n" + target_html = "<pre class=\"code highlight white plaintext\"><code>some code from $#{snippet.id}\nhere too\n</code></pre>\n" - helper.markdown("\n some code from $#{snippet.id}\n here too\n").should == target_html - helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n").should == target_html + expect(helper.markdown("\n some code from $#{snippet.id}\n here too\n")). + to eq(target_html) + expect(helper.markdown("\n```\nsome code from $#{snippet.id}\nhere too\n```\n")). + to eq(target_html) end it "should leave inline code untouched" do - markdown("\nDon't use `$#{snippet.id}` here.\n").should == + expect(markdown("\nDon't use `$#{snippet.id}` here.\n")).to eq( "<p>Don't use <code>$#{snippet.id}</code> here.</p>\n" + ) end it "should leave ref-like autolinks untouched" do - markdown("look at http://example.tld/#!#{merge_request.iid}").should == "<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n" + expect(markdown("look at http://example.tld/#!#{merge_request.iid}")).to eq("<p>look at <a href=\"http://example.tld/#!#{merge_request.iid}\">http://example.tld/#!#{merge_request.iid}</a></p>\n") end it "should leave ref-like href of 'manual' links untouched" do - markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})").should == "<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a class=\"gfm gfm-merge_request \" href=\"#{project_merge_request_url(project, merge_request)}\" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n" + expect(markdown("why not [inspect !#{merge_request.iid}](http://example.tld/#!#{merge_request.iid})")).to eq("<p>why not <a href=\"http://example.tld/#!#{merge_request.iid}\">inspect </a><a class=\"gfm gfm-merge_request \" href=\"#{namespace_project_merge_request_url(project.namespace, project, merge_request)}\" title=\"Merge Request: #{merge_request.title}\">!#{merge_request.iid}</a><a href=\"http://example.tld/#!#{merge_request.iid}\"></a></p>\n") end it "should leave ref-like src of images untouched" do - markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})").should == "<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n" + expect(markdown("screen shot: ![some image](http://example.tld/#!#{merge_request.iid})")).to eq("<p>screen shot: <img src=\"http://example.tld/#!#{merge_request.iid}\" alt=\"some image\"></p>\n") end it "should generate absolute urls for refs" do - markdown("##{issue.iid}").should include(project_issue_url(project, issue)) + expect(markdown("##{issue.iid}")).to include(namespace_project_issue_path(project.namespace, project, issue)) end it "should generate absolute urls for emoji" do - markdown(":smile:").should include("src=\"#{url_helper('emoji/smile')}") + expect(markdown(':smile:')).to( + include(%(src="#{Gitlab.config.gitlab.url}/assets/emoji/#{Emoji.emoji_filename('smile')}.png)) + ) + end + + it "should generate absolute urls for emoji if relative url is present" do + allow(Gitlab.config.gitlab).to receive(:url).and_return('http://localhost/gitlab/root') + expect(markdown(":smile:")).to include("src=\"http://localhost/gitlab/root/assets/emoji/#{Emoji.emoji_filename('smile')}.png") + end + + it "should generate absolute urls for emoji if asset_host is present" do + allow(Gitlab::Application.config).to receive(:asset_host).and_return("https://cdn.example.com") + ActionView::Base.any_instance.stub_chain(:config, :asset_host).and_return("https://cdn.example.com") + expect(markdown(":smile:")).to include("src=\"https://cdn.example.com/assets/emoji/#{Emoji.emoji_filename('smile')}.png") end + it "should handle relative urls for a file in master" do actual = "[GitLab API doc](doc/api/README.md)\n" expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) + end + + it "should handle relative urls for a file in master with an anchor" do + actual = "[GitLab API doc](doc/api/README.md#section)\n" + expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md#section\">GitLab API doc</a></p>\n" + expect(markdown(actual)).to match(expected) + end + + it "should not handle relative urls for the current file with an anchor" do + actual = "[GitLab API doc](#section)\n" + expected = "<p><a href=\"#section\">GitLab API doc</a></p>\n" + expect(markdown(actual)).to match(expected) end it "should handle relative urls for a directory in master" do actual = "[GitLab API doc](doc/api)\n" expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end it "should handle absolute urls" do actual = "[GitLab](https://www.gitlab.com)\n" expected = "<p><a href=\"https://www.gitlab.com\">GitLab</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end it "should handle relative urls in reference links for a file in master" do actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n" expected = "<p><a href=\"/#{project.path_with_namespace}/blob/#{@ref}/doc/api/README.md\">GitLab API doc</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end it "should handle relative urls in reference links for a directory in master" do actual = "[GitLab API doc directory][GitLab readmes]\n [GitLab readmes]: doc/api/\n" expected = "<p><a href=\"/#{project.path_with_namespace}/tree/#{@ref}/doc/api\">GitLab API doc directory</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end it "should not handle malformed relative urls in reference links for a file in master" do actual = "[GitLab readme]: doc/api/README.md\n" expected = "" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end it 'should allow whitelisted HTML tags from the user' do @@ -655,29 +768,29 @@ describe GitlabMarkdownHelper do it "should not touch relative urls" do actual = "[GitLab API doc][GitLab readme]\n [GitLab readme]: doc/api/README.md\n" expected = "<p><a href=\"doc/api/README.md\">GitLab API doc</a></p>\n" - markdown(actual).should match(expected) + expect(markdown(actual)).to match(expected) end end describe "#render_wiki_content" do before do @wiki = double('WikiPage') - @wiki.stub(:content).and_return('wiki content') + allow(@wiki).to receive(:content).and_return('wiki content') end it "should use GitLab Flavored Markdown for markdown files" do - @wiki.stub(:format).and_return(:markdown) + allow(@wiki).to receive(:format).and_return(:markdown) - helper.should_receive(:markdown).with('wiki content') + expect(helper).to receive(:markdown).with('wiki content') helper.render_wiki_content(@wiki) end it "should use the Gollum renderer for all other file types" do - @wiki.stub(:format).and_return(:rdoc) + allow(@wiki).to receive(:format).and_return(:rdoc) formatted_content_stub = double('formatted_content') - formatted_content_stub.should_receive(:html_safe) - @wiki.stub(:formatted_content).and_return(formatted_content_stub) + expect(formatted_content_stub).to receive(:html_safe) + allow(@wiki).to receive(:formatted_content).and_return(formatted_content_stub) helper.render_wiki_content(@wiki) end diff --git a/spec/helpers/groups_helper.rb b/spec/helpers/groups_helper.rb new file mode 100644 index 00000000000..3e99ab84ec9 --- /dev/null +++ b/spec/helpers/groups_helper.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +describe GroupsHelper do + describe 'group_icon' do + avatar_file_path = File.join(Rails.root, 'public', 'gitlab_logo.png') + + it 'should return an url for the avatar' do + group = create(:group) + group.avatar = File.open(avatar_file_path) + group.save! + expect(group_icon(group.path).to_s). + to match("/uploads/group/avatar/#{ group.id }/gitlab_logo.png") + end + + it 'should give default avatar_icon when no avatar is present' do + group = create(:group) + group.save! + expect(group_icon(group.path)).to match('group_avatar.png') + end + end +end diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb index 9c95bc044f3..54dd8d4aa64 100644 --- a/spec/helpers/issues_helper_spec.rb +++ b/spec/helpers/issues_helper_spec.rb @@ -5,133 +5,132 @@ describe IssuesHelper do let(:issue) { create :issue, project: project } let(:ext_project) { create :redmine_project } - describe :title_for_issue do + describe "title_for_issue" do it "should return issue title if used internal tracker" do @project = project - title_for_issue(issue.iid).should eq issue.title + expect(title_for_issue(issue.iid)).to eq issue.title end it "should always return empty string if used external tracker" do @project = ext_project - title_for_issue(rand(100)).should eq "" + expect(title_for_issue(rand(100))).to eq "" end it "should always return empty string if project nil" do @project = nil - title_for_issue(rand(100)).should eq "" + expect(title_for_issue(rand(100))).to eq "" end end - describe :url_for_project_issues do - let(:project_url) { Gitlab.config.issues_tracker.redmine.project_url} + describe "url_for_project_issues" do + let(:project_url) { ext_project.external_issue_tracker.project_url } let(:ext_expected) do project_url.gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) end - let(:int_expected) { polymorphic_path([project]) } + let(:int_expected) { polymorphic_path([@project.namespace, project]) } it "should return internal path if used internal tracker" do @project = project - url_for_project_issues.should match(int_expected) + expect(url_for_project_issues).to match(int_expected) end it "should return path to external tracker" do @project = ext_project - url_for_project_issues.should match(ext_expected) + expect(url_for_project_issues).to match(ext_expected) end it "should return empty string if project nil" do @project = nil - url_for_project_issues.should eq "" + expect(url_for_project_issues).to eq "" end describe "when external tracker was enabled and then config removed" do before do @project = ext_project - Gitlab.config.stub(:issues_tracker).and_return(nil) + allow(Gitlab.config).to receive(:issues_tracker).and_return(nil) end - it "should return path to internal tracker" do - url_for_project_issues.should match(polymorphic_path([@project])) + it "should return path to external tracker" do + expect(url_for_project_issues).to match(ext_expected) end end end - describe :url_for_issue do - let(:issue_id) { 3 } - let(:issues_url) { Gitlab.config.issues_tracker.redmine.issues_url} + describe "url_for_issue" do + let(:issues_url) { ext_project.external_issue_tracker.issues_url} let(:ext_expected) do - issues_url.gsub(':id', issue_id.to_s) + issues_url.gsub(':id', issue.iid.to_s) .gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) end - let(:int_expected) { polymorphic_path([project, issue]) } + let(:int_expected) { polymorphic_path([@project.namespace, project, issue]) } it "should return internal path if used internal tracker" do @project = project - url_for_issue(issue.iid).should match(int_expected) + expect(url_for_issue(issue.iid)).to match(int_expected) end it "should return path to external tracker" do @project = ext_project - url_for_issue(issue_id).should match(ext_expected) + expect(url_for_issue(issue.iid)).to match(ext_expected) end it "should return empty string if project nil" do @project = nil - url_for_issue(issue.iid).should eq "" + expect(url_for_issue(issue.iid)).to eq "" end describe "when external tracker was enabled and then config removed" do before do @project = ext_project - Gitlab.config.stub(:issues_tracker).and_return(nil) + allow(Gitlab.config).to receive(:issues_tracker).and_return(nil) end - it "should return internal path" do - url_for_issue(issue.iid).should match(polymorphic_path([@project, issue])) + it "should return external path" do + expect(url_for_issue(issue.iid)).to match(ext_expected) end end end - describe :url_for_new_issue do - let(:issues_url) { Gitlab.config.issues_tracker.redmine.new_issue_url} + describe '#url_for_new_issue' do + let(:issues_url) { ext_project.external_issue_tracker.new_issue_url } let(:ext_expected) do issues_url.gsub(':project_id', ext_project.id.to_s) .gsub(':issues_tracker_id', ext_project.issues_tracker_id.to_s) end - let(:int_expected) { new_project_issue_path(project) } + let(:int_expected) { new_namespace_project_issue_path(project.namespace, project) } it "should return internal path if used internal tracker" do @project = project - url_for_new_issue.should match(int_expected) + expect(url_for_new_issue).to match(int_expected) end it "should return path to external tracker" do @project = ext_project - url_for_new_issue.should match(ext_expected) + expect(url_for_new_issue).to match(ext_expected) end it "should return empty string if project nil" do @project = nil - url_for_new_issue.should eq "" + expect(url_for_new_issue).to eq "" end describe "when external tracker was enabled and then config removed" do before do @project = ext_project - Gitlab.config.stub(:issues_tracker).and_return(nil) + allow(Gitlab.config).to receive(:issues_tracker).and_return(nil) end it "should return internal path" do - url_for_new_issue.should match(new_project_issue_path(@project)) + expect(url_for_new_issue).to match(ext_expected) end end end diff --git a/spec/helpers/merge_requests_helper.rb b/spec/helpers/merge_requests_helper.rb index 5a317c4886b..5262d644048 100644 --- a/spec/helpers/merge_requests_helper.rb +++ b/spec/helpers/merge_requests_helper.rb @@ -7,6 +7,6 @@ describe MergeRequestsHelper do [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)] end - it { should eq('#1, #2, and #3') } + it { is_expected.to eq('#1, #2, and #3') } end end diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb new file mode 100644 index 00000000000..e4d18d8bfc6 --- /dev/null +++ b/spec/helpers/nav_helper_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the NavHelper. For example: +# +# describe NavHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +describe NavHelper do + describe '#nav_menu_collapsed?' do + it 'returns true when the nav is collapsed in the cookie' do + helper.request.cookies[:collapsed_nav] = 'true' + expect(helper.nav_menu_collapsed?).to eq true + end + + it 'returns false when the nav is not collapsed in the cookie' do + helper.request.cookies[:collapsed_nav] = 'false' + expect(helper.nav_menu_collapsed?).to eq false + end + end +end diff --git a/spec/helpers/notifications_helper_spec.rb b/spec/helpers/notifications_helper_spec.rb index 31ecdacf28e..482cb33e94f 100644 --- a/spec/helpers/notifications_helper_spec.rb +++ b/spec/helpers/notifications_helper_spec.rb @@ -1,6 +1,9 @@ require 'spec_helper' describe NotificationsHelper do + include FontAwesome::Rails::IconHelper + include IconsHelper + describe 'notification_icon' do let(:notification) { double(disabled?: false, participating?: false, watch?: false) } @@ -8,7 +11,7 @@ describe NotificationsHelper do before { notification.stub(disabled?: true) } it "has a red icon" do - notification_icon(notification).should match('class="fa fa-volume-off ns-mute"') + expect(notification_icon(notification)).to match('class="fa fa-volume-off ns-mute"') end end @@ -16,7 +19,7 @@ describe NotificationsHelper do before { notification.stub(participating?: true) } it "has a blue icon" do - notification_icon(notification).should match('class="fa fa-volume-down ns-part"') + expect(notification_icon(notification)).to match('class="fa fa-volume-down ns-part"') end end @@ -24,12 +27,12 @@ describe NotificationsHelper do before { notification.stub(watch?: true) } it "has a green icon" do - notification_icon(notification).should match('class="fa fa-volume-up ns-watch"') + expect(notification_icon(notification)).to match('class="fa fa-volume-up ns-watch"') end end it "has a blue icon" do - notification_icon(notification).should match('class="fa fa-circle-o ns-default"') + expect(notification_icon(notification)).to match('class="fa fa-circle-o ns-default"') end end end diff --git a/spec/helpers/oauth_helper_spec.rb b/spec/helpers/oauth_helper_spec.rb new file mode 100644 index 00000000000..088c342fa13 --- /dev/null +++ b/spec/helpers/oauth_helper_spec.rb @@ -0,0 +1,20 @@ +require "spec_helper" + +describe OauthHelper do + describe "additional_providers" do + it 'returns all enabled providers' do + allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :github] } + expect(helper.additional_providers).to include(*[:twitter, :github]) + end + + it 'does not return ldap provider' do + allow(helper).to receive(:enabled_oauth_providers) { [:twitter, :ldapmain] } + expect(helper.additional_providers).to include(:twitter) + end + + it 'returns empty array' do + allow(helper).to receive(:enabled_oauth_providers) { [] } + expect(helper.additional_providers).to eq([]) + end + end +end
\ No newline at end of file diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb index 114058e3095..0f78725e3d9 100644 --- a/spec/helpers/projects_helper_spec.rb +++ b/spec/helpers/projects_helper_spec.rb @@ -1,23 +1,11 @@ require 'spec_helper' describe ProjectsHelper do - describe '#project_issues_trackers' do - it "returns the correct issues trackers available" do - project_issues_trackers.should == - "<option value=\"redmine\">Redmine</option>\n" \ - "<option value=\"gitlab\">GitLab</option>" - end - - it "returns the correct issues trackers available with current tracker 'gitlab' selected" do - project_issues_trackers('gitlab').should == - "<option value=\"redmine\">Redmine</option>\n" \ - "<option selected=\"selected\" value=\"gitlab\">GitLab</option>" - end - - it "returns the correct issues trackers available with current tracker 'redmine' selected" do - project_issues_trackers('redmine').should == - "<option selected=\"selected\" value=\"redmine\">Redmine</option>\n" \ - "<option value=\"gitlab\">GitLab</option>" + describe "#project_status_css_class" do + it "returns appropriate class" do + expect(project_status_css_class("started")).to eq("active") + expect(project_status_css_class("failed")).to eq("danger") + expect(project_status_css_class("finished")).to eq("success") end end end diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb index 733f2754727..b327f4f911a 100644 --- a/spec/helpers/search_helper_spec.rb +++ b/spec/helpers/search_helper_spec.rb @@ -13,7 +13,7 @@ describe SearchHelper do end it "it returns nil" do - search_autocomplete_opts("q").should be_nil + expect(search_autocomplete_opts("q")).to be_nil end end @@ -25,29 +25,29 @@ describe SearchHelper do end it "includes Help sections" do - search_autocomplete_opts("hel").size.should == 9 + expect(search_autocomplete_opts("hel").size).to eq(9) end it "includes default sections" do - search_autocomplete_opts("adm").size.should == 1 + expect(search_autocomplete_opts("adm").size).to eq(1) end it "includes the user's groups" do create(:group).add_owner(user) - search_autocomplete_opts("gro").size.should == 1 + expect(search_autocomplete_opts("gro").size).to eq(1) end it "includes the user's projects" do project = create(:project, namespace: create(:namespace, owner: user)) - search_autocomplete_opts(project.name).size.should == 1 + expect(search_autocomplete_opts(project.name).size).to eq(1) end context "with a current project" do before { @project = create(:project) } it "includes project-specific sections" do - search_autocomplete_opts("Files").size.should == 1 - search_autocomplete_opts("Commits").size.should == 1 + expect(search_autocomplete_opts("Files").size).to eq(1) + expect(search_autocomplete_opts("Commits").size).to eq(1) end end end diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb index 41c9f038c26..aef1108e333 100644 --- a/spec/helpers/submodule_helper_spec.rb +++ b/spec/helpers/submodule_helper_spec.rb @@ -19,28 +19,28 @@ describe SubmoduleHelper do Gitlab.config.gitlab_shell.stub(ssh_port: 22) # set this just to be sure Gitlab.config.gitlab_shell.stub(ssh_path_prefix: Settings.send(:build_gitlab_shell_ssh_path_prefix)) stub_url([ config.user, '@', config.host, ':gitlab-org/gitlab-ce.git' ].join('')) - submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] + expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ]) end it 'should detect ssh on non-standard port' do Gitlab.config.gitlab_shell.stub(ssh_port: 2222) Gitlab.config.gitlab_shell.stub(ssh_path_prefix: Settings.send(:build_gitlab_shell_ssh_path_prefix)) stub_url([ 'ssh://', config.user, '@', config.host, ':2222/gitlab-org/gitlab-ce.git' ].join('')) - submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] + expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ]) end it 'should detect http on standard port' do Gitlab.config.gitlab.stub(port: 80) Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url)) stub_url([ 'http://', config.host, '/gitlab-org/gitlab-ce.git' ].join('')) - submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] + expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ]) end it 'should detect http on non-standard port' do Gitlab.config.gitlab.stub(port: 3000) Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url)) stub_url([ 'http://', config.host, ':3000/gitlab-org/gitlab-ce.git' ].join('')) - submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] + expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ]) end it 'should work with relative_url_root' do @@ -48,67 +48,67 @@ describe SubmoduleHelper do Gitlab.config.gitlab.stub(relative_url_root: '/gitlab/root') Gitlab.config.gitlab.stub(url: Settings.send(:build_gitlab_url)) stub_url([ 'http://', config.host, '/gitlab/root/gitlab-org/gitlab-ce.git' ].join('')) - submodule_links(submodule_item).should == [ project_path('gitlab-org/gitlab-ce'), project_tree_path('gitlab-org/gitlab-ce', 'hash') ] + expect(submodule_links(submodule_item)).to eq([ namespace_project_path('gitlab-org', 'gitlab-ce'), namespace_project_tree_path('gitlab-org', 'gitlab-ce', 'hash') ]) end end context 'submodule on github.com' do it 'should detect ssh' do stub_url('git@github.com:gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should detect http' do stub_url('http://github.com/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should detect https' do stub_url('https://github.com/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://github.com/gitlab-org/gitlab-ce', 'https://github.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should return original with non-standard url' do stub_url('http://github.com/gitlab-org/gitlab-ce') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) stub_url('http://github.com/another/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) end end context 'submodule on gitlab.com' do it 'should detect ssh' do stub_url('git@gitlab.com:gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should detect http' do stub_url('http://gitlab.com/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should detect https' do stub_url('https://gitlab.com/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ] + expect(submodule_links(submodule_item)).to eq([ 'https://gitlab.com/gitlab-org/gitlab-ce', 'https://gitlab.com/gitlab-org/gitlab-ce/tree/hash' ]) end it 'should return original with non-standard url' do stub_url('http://gitlab.com/gitlab-org/gitlab-ce') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) stub_url('http://gitlab.com/another/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) end end context 'submodule on unsupported' do it 'should return original' do stub_url('http://mygitserver.com/gitlab-org/gitlab-ce') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) stub_url('http://mygitserver.com/gitlab-org/gitlab-ce.git') - submodule_links(submodule_item).should == [ repo.submodule_url_for, nil ] + expect(submodule_links(submodule_item)).to eq([ repo.submodule_url_for, nil ]) end end end diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb index fa8a3f554f7..fc0ceecfbe7 100644 --- a/spec/helpers/tab_helper_spec.rb +++ b/spec/helpers/tab_helper_spec.rb @@ -5,40 +5,40 @@ describe TabHelper do describe 'nav_link' do before do - controller.stub(:controller_name).and_return('foo') + allow(controller).to receive(:controller_name).and_return('foo') allow(self).to receive(:action_name).and_return('foo') end it "captures block output" do - nav_link { "Testing Blocks" }.should match(/Testing Blocks/) + expect(nav_link { "Testing Blocks" }).to match(/Testing Blocks/) end it "performs checks on the current controller" do - nav_link(controller: :foo).should match(/<li class="active">/) - nav_link(controller: :bar).should_not match(/active/) - nav_link(controller: [:foo, :bar]).should match(/active/) + expect(nav_link(controller: :foo)).to match(/<li class="active">/) + expect(nav_link(controller: :bar)).not_to match(/active/) + expect(nav_link(controller: [:foo, :bar])).to match(/active/) end it "performs checks on the current action" do - nav_link(action: :foo).should match(/<li class="active">/) - nav_link(action: :bar).should_not match(/active/) - nav_link(action: [:foo, :bar]).should match(/active/) + expect(nav_link(action: :foo)).to match(/<li class="active">/) + expect(nav_link(action: :bar)).not_to match(/active/) + expect(nav_link(action: [:foo, :bar])).to match(/active/) end it "performs checks on both controller and action when both are present" do - nav_link(controller: :bar, action: :foo).should_not match(/active/) - nav_link(controller: :foo, action: :bar).should_not match(/active/) - nav_link(controller: :foo, action: :foo).should match(/active/) + expect(nav_link(controller: :bar, action: :foo)).not_to match(/active/) + expect(nav_link(controller: :foo, action: :bar)).not_to match(/active/) + expect(nav_link(controller: :foo, action: :foo)).to match(/active/) end it "accepts a path shorthand" do - nav_link(path: 'foo#bar').should_not match(/active/) - nav_link(path: 'foo#foo').should match(/active/) + expect(nav_link(path: 'foo#bar')).not_to match(/active/) + expect(nav_link(path: 'foo#foo')).to match(/active/) end it "passes extra html options to the list element" do - nav_link(action: :foo, html_options: {class: 'home'}).should match(/<li class="home active">/) - nav_link(html_options: {class: 'active'}).should match(/<li class="active">/) + expect(nav_link(action: :foo, html_options: {class: 'home'})).to match(/<li class="home active">/) + expect(nav_link(html_options: {class: 'active'})).to match(/<li class="active">/) end end end diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb new file mode 100644 index 00000000000..8271e00f41b --- /dev/null +++ b/spec/helpers/tree_helper_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe TreeHelper do + describe 'flatten_tree' do + let(:project) { create(:project) } + + before { + @repository = project.repository + @commit = project.repository.commit("e56497bb") + } + + context "on a directory containing more than one file/directory" do + let(:tree_item) { double(name: "files", path: "files") } + + it "should return the directory name" do + expect(flatten_tree(tree_item)).to match('files') + end + end + + context "on a directory containing only one directory" do + let(:tree_item) { double(name: "foo", path: "foo") } + + it "should return the flattened path" do + expect(flatten_tree(tree_item)).to match('foo/bar') + end + end + end +end diff --git a/spec/lib/disable_email_interceptor_spec.rb b/spec/lib/disable_email_interceptor_spec.rb new file mode 100644 index 00000000000..06d5450688b --- /dev/null +++ b/spec/lib/disable_email_interceptor_spec.rb @@ -0,0 +1,26 @@ +require 'spec_helper' + +describe DisableEmailInterceptor do + before do + ActionMailer::Base.register_interceptor(DisableEmailInterceptor) + end + + it 'should not send emails' do + allow(Gitlab.config.gitlab).to receive(:email_enabled).and_return(false) + expect { + deliver_mail + }.not_to change(ActionMailer::Base.deliveries, :count) + end + + after do + # Removing interceptor from the list because unregister_interceptor is + # implemented in later version of mail gem + # See: https://github.com/mikel/mail/pull/705 + Mail.class_variable_set(:@@delivery_interceptors, []) + end + + def deliver_mail + key = create :personal_key + Notify.new_ssh_key_email(key.id) + end +end diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index 7b3818ea5c8..ac602eac154 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -14,44 +14,46 @@ describe ExtractsPath do describe '#extract_ref' do it "returns an empty pair when no @project is set" do @project = nil - extract_ref('master/CHANGELOG').should == ['', ''] + expect(extract_ref('master/CHANGELOG')).to eq(['', '']) end context "without a path" do it "extracts a valid branch" do - extract_ref('master').should == ['master', ''] + expect(extract_ref('master')).to eq(['master', '']) end it "extracts a valid tag" do - extract_ref('v2.0.0').should == ['v2.0.0', ''] + expect(extract_ref('v2.0.0')).to eq(['v2.0.0', '']) end it "extracts a valid commit ref without a path" do - extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062').should == + expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062')).to eq( ['f4b14494ef6abf3d144c28e4af0c20143383e062', ''] + ) end it "falls back to a primitive split for an invalid ref" do - extract_ref('stable').should == ['stable', ''] + expect(extract_ref('stable')).to eq(['stable', '']) end end context "with a path" do it "extracts a valid branch" do - extract_ref('foo/bar/baz/CHANGELOG').should == ['foo/bar/baz', 'CHANGELOG'] + expect(extract_ref('foo/bar/baz/CHANGELOG')).to eq(['foo/bar/baz', 'CHANGELOG']) end it "extracts a valid tag" do - extract_ref('v2.0.0/CHANGELOG').should == ['v2.0.0', 'CHANGELOG'] + expect(extract_ref('v2.0.0/CHANGELOG')).to eq(['v2.0.0', 'CHANGELOG']) end it "extracts a valid commit SHA" do - extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG').should == + expect(extract_ref('f4b14494ef6abf3d144c28e4af0c20143383e062/CHANGELOG')).to eq( ['f4b14494ef6abf3d144c28e4af0c20143383e062', 'CHANGELOG'] + ) end it "falls back to a primitive split for an invalid ref" do - extract_ref('stable/CHANGELOG').should == ['stable', 'CHANGELOG'] + expect(extract_ref('stable/CHANGELOG')).to eq(['stable', 'CHANGELOG']) end end end diff --git a/spec/lib/git_ref_validator_spec.rb b/spec/lib/git_ref_validator_spec.rb index b2469c18395..4633b6f3934 100644 --- a/spec/lib/git_ref_validator_spec.rb +++ b/spec/lib/git_ref_validator_spec.rb @@ -1,20 +1,20 @@ require 'spec_helper' describe Gitlab::GitRefValidator do - it { Gitlab::GitRefValidator.validate('feature/new').should be_true } - it { Gitlab::GitRefValidator.validate('implement_@all').should be_true } - it { Gitlab::GitRefValidator.validate('my_new_feature').should be_true } - it { Gitlab::GitRefValidator.validate('#1').should be_true } - it { Gitlab::GitRefValidator.validate('feature/~new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/^new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/:new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/?new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/*new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/[new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/new/').should be_false } - it { Gitlab::GitRefValidator.validate('feature/new.').should be_false } - it { Gitlab::GitRefValidator.validate('feature\@{').should be_false } - it { Gitlab::GitRefValidator.validate('feature\new').should be_false } - it { Gitlab::GitRefValidator.validate('feature//new').should be_false } - it { Gitlab::GitRefValidator.validate('feature new').should be_false } + it { expect(Gitlab::GitRefValidator.validate('feature/new')).to be_truthy } + it { expect(Gitlab::GitRefValidator.validate('implement_@all')).to be_truthy } + it { expect(Gitlab::GitRefValidator.validate('my_new_feature')).to be_truthy } + it { expect(Gitlab::GitRefValidator.validate('#1')).to be_truthy } + it { expect(Gitlab::GitRefValidator.validate('feature/~new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/^new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/:new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/?new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/*new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/[new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/new/')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature/new.')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature\@{')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature\new')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature//new')).to be_falsey } + it { expect(Gitlab::GitRefValidator.validate('feature new')).to be_falsey } end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 551fb3fb5f6..95fc7e16a11 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -10,13 +10,21 @@ describe Gitlab::Auth do password: password, password_confirmation: password) end - let(:username) { 'john' } + let(:username) { 'John' } # username isn't lowercase, test this let(:password) { 'my-secret' } it "should find user by valid login/password" do expect( gl_auth.find(username, password) ).to eql user end + it 'should find user by valid email/password with case-insensitive email' do + expect(gl_auth.find(user.email.upcase, password)).to eql user + end + + it 'should find user by valid username/password with case-insensitive username' do + expect(gl_auth.find(username.upcase, password)).to eql user + end + it "should not find user with invalid password" do password = 'wrong' expect( gl_auth.find(username, password) ).to_not eql user @@ -28,17 +36,16 @@ describe Gitlab::Auth do end context "with ldap enabled" do - before { Gitlab.config.ldap['enabled'] = true } - after { Gitlab.config.ldap['enabled'] = false } + before { Gitlab::LDAP::Config.stub(enabled?: true) } it "tries to autheticate with db before ldap" do - expect(Gitlab::LDAP::User).not_to receive(:authenticate) + expect(Gitlab::LDAP::Authentication).not_to receive(:login) gl_auth.find(username, password) end it "uses ldap as fallback to for authentication" do - expect(Gitlab::LDAP::User).to receive(:authenticate) + expect(Gitlab::LDAP::Authentication).to receive(:login) gl_auth.find('ldap_user', 'password') end diff --git a/spec/lib/gitlab/backend/grack_auth_spec.rb b/spec/lib/gitlab/backend/grack_auth_spec.rb new file mode 100644 index 00000000000..768312f0028 --- /dev/null +++ b/spec/lib/gitlab/backend/grack_auth_spec.rb @@ -0,0 +1,146 @@ +require "spec_helper" + +describe Grack::Auth do + let(:user) { create(:user) } + let(:project) { create(:project) } + + let(:app) { lambda { |env| [200, {}, "Success!"] } } + let!(:auth) { Grack::Auth.new(app) } + let(:env) { + { + "rack.input" => "", + "REQUEST_METHOD" => "GET", + "QUERY_STRING" => "service=git-upload-pack" + } + } + let(:status) { auth.call(env).first } + + describe "#call" do + context "when the project doesn't exist" do + before do + env["PATH_INFO"] = "doesnt/exist.git" + end + + context "when no authentication is provided" do + it "responds with status 401" do + expect(status).to eq(401) + end + end + + context "when username and password are provided" do + context "when authentication fails" do + before do + env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope") + end + + it "responds with status 401" do + expect(status).to eq(401) + end + end + + context "when authentication succeeds" do + before do + env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) + end + + it "responds with status 404" do + expect(status).to eq(404) + end + end + end + end + + context "when the project exists" do + before do + env["PATH_INFO"] = project.path_with_namespace + ".git" + end + + context "when the project is public" do + before do + project.update_attribute(:visibility_level, Project::PUBLIC) + end + + it "responds with status 200" do + expect(status).to eq(200) + end + end + + context "when the project is private" do + before do + project.update_attribute(:visibility_level, Project::PRIVATE) + end + + context "when no authentication is provided" do + it "responds with status 401" do + expect(status).to eq(401) + end + end + + context "when username and password are provided" do + context "when authentication fails" do + before do + env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, "nope") + end + + it "responds with status 401" do + expect(status).to eq(401) + end + end + + context "when authentication succeeds" do + before do + env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials(user.username, user.password) + end + + context "when the user has access to the project" do + before do + project.team << [user, :master] + end + + context "when the user is blocked" do + before do + user.block + project.team << [user, :master] + end + + it "responds with status 404" do + expect(status).to eq(404) + end + end + + context "when the user isn't blocked" do + it "responds with status 200" do + expect(status).to eq(200) + end + end + end + + context "when the user doesn't have access to the project" do + it "responds with status 404" do + expect(status).to eq(404) + end + end + end + end + + context "when a gitlab ci token is provided" do + let(:token) { "123" } + + before do + gitlab_ci_service = project.build_gitlab_ci_service + gitlab_ci_service.active = true + gitlab_ci_service.token = token + gitlab_ci_service.project_url = "http://google.com" + gitlab_ci_service.save + + env["HTTP_AUTHORIZATION"] = ActionController::HttpAuthentication::Basic.encode_credentials("gitlab-ci-token", token) + end + + it "responds with status 200" do + expect(status).to eq(200) + end + end + end + end + end +end diff --git a/spec/lib/gitlab/backend/shell_spec.rb b/spec/lib/gitlab/backend/shell_spec.rb index f00ec0fa401..27279465c1a 100644 --- a/spec/lib/gitlab/backend/shell_spec.rb +++ b/spec/lib/gitlab/backend/shell_spec.rb @@ -8,11 +8,11 @@ describe Gitlab::Shell do Project.stub(find: project) end - it { should respond_to :add_key } - it { should respond_to :remove_key } - it { should respond_to :add_repository } - it { should respond_to :remove_repository } - it { should respond_to :fork_repository } + it { is_expected.to respond_to :add_key } + it { is_expected.to respond_to :remove_key } + it { is_expected.to respond_to :add_repository } + it { is_expected.to respond_to :remove_repository } + it { is_expected.to respond_to :fork_repository } - it { gitlab_shell.url_to_repo('diaspora').should == Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git" } + it { expect(gitlab_shell.url_to_repo('diaspora')).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + "diaspora.git") } end diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb new file mode 100644 index 00000000000..f5523105848 --- /dev/null +++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe Gitlab::BitbucketImport::ProjectCreator do + let(:user) { create(:user, bitbucket_access_token: "asdffg", bitbucket_access_token_secret: "sekret") } + let(:repo) { { + name: 'Vim', + slug: 'vim', + is_private: true, + owner: "asd"}.with_indifferent_access + } + let(:namespace){ create(:namespace) } + + it 'creates project' do + allow_any_instance_of(Project).to receive(:add_import_job) + + project_creator = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, user) + project = project_creator.execute + + expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git") + expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end +end diff --git a/spec/lib/gitlab/closing_issue_extractor_spec.rb b/spec/lib/gitlab/closing_issue_extractor_spec.rb new file mode 100644 index 00000000000..c96ee78e5fd --- /dev/null +++ b/spec/lib/gitlab/closing_issue_extractor_spec.rb @@ -0,0 +1,174 @@ +require 'spec_helper' + +describe Gitlab::ClosingIssueExtractor do + let(:project) { create(:project) } + let(:issue) { create(:issue, project: project) } + let(:iid1) { issue.iid } + + describe :closed_by_message_in_project do + context 'with a single reference' do + it do + message = "Awesome commit (Closes ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Awesome commit (closes ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Closed ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "closed ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Closing ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "closing ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Close ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "close ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Awesome commit (Fixes ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Awesome commit (fixes ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Fixed ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "fixed ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Fixing ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "fixing ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Fix ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "fix ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Awesome commit (Resolves ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Awesome commit (resolves ##{iid1})" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Resolved ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "resolved ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Resolving ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "resolving ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "Resolve ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + + it do + message = "resolve ##{iid1}" + expect(subject.closed_by_message_in_project(message, project)).to eq([issue]) + end + end + + context 'with multiple references' do + let(:other_issue) { create(:issue, project: project) } + let(:third_issue) { create(:issue, project: project) } + let(:iid2) { other_issue.iid } + let(:iid3) { third_issue.iid } + + it 'fetches issues in single line message' do + message = "Closes ##{iid1} and fix ##{iid2}" + + expect(subject.closed_by_message_in_project(message, project)). + to eq([issue, other_issue]) + end + + it 'fetches comma-separated issues references in single line message' do + message = "Closes ##{iid1}, closes ##{iid2}" + + expect(subject.closed_by_message_in_project(message, project)). + to eq([issue, other_issue]) + end + + it 'fetches comma-separated issues numbers in single line message' do + message = "Closes ##{iid1}, ##{iid2} and ##{iid3}" + + expect(subject.closed_by_message_in_project(message, project)). + to eq([issue, other_issue, third_issue]) + end + + it 'fetches issues in multi-line message' do + message = "Awesome commit (closes ##{iid1})\nAlso fixes ##{iid2}" + + expect(subject.closed_by_message_in_project(message, project)). + to eq([issue, other_issue]) + end + + it 'fetches issues in hybrid message' do + message = "Awesome commit (closes ##{iid1})\n"\ + "Also fixing issues ##{iid2}, ##{iid3} and #4" + + expect(subject.closed_by_message_in_project(message, project)). + to eq([issue, other_issue, third_issue]) + end + end + end +end diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index cf0b5c282c1..40eb45e37ca 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -11,11 +11,11 @@ describe Gitlab::Diff::File do describe :diff_lines do let(:diff_lines) { diff_file.diff_lines } - it { diff_lines.size.should == 30 } - it { diff_lines.first.should be_kind_of(Gitlab::Diff::Line) } + it { expect(diff_lines.size).to eq(30) } + it { expect(diff_lines.first).to be_kind_of(Gitlab::Diff::Line) } end describe :mode_changed? do - it { diff_file.mode_changed?.should be_false } + it { expect(diff_file.mode_changed?).to be_falsey } end end diff --git a/spec/lib/gitlab/diff/parser_spec.rb b/spec/lib/gitlab/diff/parser_spec.rb index 35b78260acd..918f6d0ead4 100644 --- a/spec/lib/gitlab/diff/parser_spec.rb +++ b/spec/lib/gitlab/diff/parser_spec.rb @@ -50,43 +50,43 @@ eos @lines = parser.parse(diff.lines) end - it { @lines.size.should == 30 } + it { expect(@lines.size).to eq(30) } describe 'lines' do describe 'first line' do let(:line) { @lines.first } - it { line.type.should == 'match' } - it { line.old_pos.should == 6 } - it { line.new_pos.should == 6 } - it { line.text.should == '@@ -6,12 +6,18 @@ module Popen' } + it { expect(line.type).to eq('match') } + it { expect(line.old_pos).to eq(6) } + it { expect(line.new_pos).to eq(6) } + it { expect(line.text).to eq('@@ -6,12 +6,18 @@ module Popen') } end describe 'removal line' do let(:line) { @lines[10] } - it { line.type.should == 'old' } - it { line.old_pos.should == 14 } - it { line.new_pos.should == 13 } - it { line.text.should == '- options = { chdir: path }' } + it { expect(line.type).to eq('old') } + it { expect(line.old_pos).to eq(14) } + it { expect(line.new_pos).to eq(13) } + it { expect(line.text).to eq('- options = { chdir: path }') } end describe 'addition line' do let(:line) { @lines[16] } - it { line.type.should == 'new' } - it { line.old_pos.should == 15 } - it { line.new_pos.should == 18 } - it { line.text.should == '+ options = {' } + it { expect(line.type).to eq('new') } + it { expect(line.old_pos).to eq(15) } + it { expect(line.new_pos).to eq(18) } + it { expect(line.text).to eq('+ options = {') } end describe 'unchanged line' do let(:line) { @lines.last } - it { line.type.should == nil } - it { line.old_pos.should == 24 } - it { line.new_pos.should == 31 } - it { line.text.should == ' @cmd_output << stderr.read' } + it { expect(line.type).to eq(nil) } + it { expect(line.old_pos).to eq(24) } + it { expect(line.new_pos).to eq(31) } + it { expect(line.text).to eq(' @cmd_output << stderr.read') } end end end diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb index 570b03827a8..666398eedd4 100644 --- a/spec/lib/gitlab/git_access_spec.rb +++ b/spec/lib/gitlab/git_access_spec.rb @@ -5,14 +5,76 @@ describe Gitlab::GitAccess do let(:project) { create(:project) } let(:user) { create(:user) } - describe 'download_allowed?' do + describe 'can_push_to_branch?' do + describe 'push to none protected branch' do + it "returns true if user is a master" do + project.team << [user, :master] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch")).to be_truthy + end + + it "returns true if user is a developer" do + project.team << [user, :developer] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch")).to be_truthy + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, "random_branch")).to be_falsey + end + end + + describe 'push to protected branch' do + before do + @branch = create :protected_branch, project: project + end + + it "returns true if user is a master" do + project.team << [user, :master] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_truthy + end + + it "returns false if user is a developer" do + project.team << [user, :developer] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_falsey + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_falsey + end + end + + describe 'push to protected branch if allowed for developers' do + before do + @branch = create :protected_branch, project: project, developers_can_push: true + end + + it "returns true if user is a master" do + project.team << [user, :master] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_truthy + end + + it "returns true if user is a developer" do + project.team << [user, :developer] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_truthy + end + + it "returns false if user is a reporter" do + project.team << [user, :reporter] + expect(Gitlab::GitAccess.can_push_to_branch?(user, project, @branch.name)).to be_falsey + end + end + + end + + describe 'download_access_check' do describe 'master permissions' do before { project.team << [user, :master] } context 'pull code' do - subject { access.download_allowed?(user, project) } + subject { access.download_access_check(user, project) } - it { should be_true } + it { expect(subject.allowed?).to be_truthy } end end @@ -20,9 +82,9 @@ describe Gitlab::GitAccess do before { project.team << [user, :guest] } context 'pull code' do - subject { access.download_allowed?(user, project) } + subject { access.download_access_check(user, project) } - it { should be_false } + it { expect(subject.allowed?).to be_falsey } end end @@ -33,34 +95,54 @@ describe Gitlab::GitAccess do end context 'pull code' do - subject { access.download_allowed?(user, project) } + subject { access.download_access_check(user, project) } - it { should be_false } + it { expect(subject.allowed?).to be_falsey } end end describe 'without acccess to project' do context 'pull code' do - subject { access.download_allowed?(user, project) } + subject { access.download_access_check(user, project) } + + it { expect(subject.allowed?).to be_falsey } + end + end + + describe 'deploy key permissions' do + let(:key) { create(:deploy_key) } + + context 'pull code' do + context 'allowed' do + before { key.projects << project } + subject { access.download_access_check(key, project) } + + it { expect(subject.allowed?).to be_truthy } + end + + context 'denied' do + subject { access.download_access_check(key, project) } - it { should be_false } + it { expect(subject.allowed?).to be_falsey } + end end end end - describe 'push_allowed?' do + describe 'push_access_check' do def protect_feature_branch create(:protected_branch, name: 'feature', project: project) end def changes { - push_new_branch: '000000000 570e7b2ab refs/heads/wow', + push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow", push_master: '6f6d7e7ed 570e7b2ab refs/heads/master', push_protected_branch: '6f6d7e7ed 570e7b2ab refs/heads/feature', - push_remove_protected_branch: '570e7b2ab 000000000 refs/heads/feature', + push_remove_protected_branch: "570e7b2ab #{Gitlab::Git::BLANK_SHA} "\ + 'refs/heads/feature', push_tag: '6f6d7e7ed 570e7b2ab refs/tags/v1.0.0', - push_new_tag: '000000000 570e7b2ab refs/tags/v7.8.9', + push_new_tag: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/tags/v7.8.9", push_all: ['6f6d7e7ed 570e7b2ab refs/heads/master', '6f6d7e7ed 570e7b2ab refs/heads/feature'] } end @@ -109,6 +191,13 @@ describe Gitlab::GitAccess do } end + def self.updated_permissions_matrix + updated_permissions_matrix = permissions_matrix.dup + updated_permissions_matrix[:developer][:push_protected_branch] = true + updated_permissions_matrix[:developer][:push_all] = true + updated_permissions_matrix + end + permissions_matrix.keys.each do |role| describe "#{role} access" do before { protect_feature_branch } @@ -116,9 +205,26 @@ describe Gitlab::GitAccess do permissions_matrix[role].each do |action, allowed| context action do - subject { access.push_allowed?(user, project, changes[action]) } + subject { access.push_access_check(user, project, changes[action]) } + + it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } + end + end + end + end + + context "with enabled developers push to protected branches " do + updated_permissions_matrix.keys.each do |role| + describe "#{role} access" do + before { create(:protected_branch, name: 'feature', developers_can_push: true, project: project) } + before { project.team << [user, role] } + + updated_permissions_matrix[role].each do |action, allowed| + context action do + subject { access.push_access_check(user, project, changes[action]) } - it { should allowed ? be_true : be_false } + it { expect(subject.allowed?).to allowed ? be_truthy : be_falsey } + end end end end diff --git a/spec/lib/gitlab/git_access_wiki_spec.rb b/spec/lib/gitlab/git_access_wiki_spec.rb index ed5785b31e6..c31c6764091 100644 --- a/spec/lib/gitlab/git_access_wiki_spec.rb +++ b/spec/lib/gitlab/git_access_wiki_spec.rb @@ -11,9 +11,9 @@ describe Gitlab::GitAccessWiki do project.team << [user, :developer] end - subject { access.push_allowed?(user, project, changes) } + subject { access.push_access_check(user, project, changes) } - it { should be_true } + it { expect(subject.allowed?).to be_truthy } end def changes diff --git a/spec/lib/gitlab/github_import/project_creator_spec.rb b/spec/lib/gitlab/github_import/project_creator_spec.rb new file mode 100644 index 00000000000..8d594a112d4 --- /dev/null +++ b/spec/lib/gitlab/github_import/project_creator_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Gitlab::GithubImport::ProjectCreator do + let(:user) { create(:user, github_access_token: "asdffg") } + let(:repo) { OpenStruct.new( + login: 'vim', + name: 'vim', + private: true, + full_name: 'asd/vim', + clone_url: "https://gitlab.com/asd/vim.git", + owner: OpenStruct.new(login: "john")) + } + let(:namespace){ create(:namespace) } + + it 'creates project' do + allow_any_instance_of(Project).to receive(:add_import_job) + + project_creator = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, user) + project = project_creator.execute + + expect(project.import_url).to eq("https://asdffg@gitlab.com/asd/vim.git") + expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end +end diff --git a/spec/lib/gitlab/gitlab_import/project_creator_spec.rb b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb new file mode 100644 index 00000000000..4c0d64ed138 --- /dev/null +++ b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Gitlab::GitlabImport::ProjectCreator do + let(:user) { create(:user, gitlab_access_token: "asdffg") } + let(:repo) { { + name: 'vim', + path: 'vim', + visibility_level: Gitlab::VisibilityLevel::PRIVATE, + path_with_namespace: 'asd/vim', + http_url_to_repo: "https://gitlab.com/asd/vim.git", + owner: {name: "john"}}.with_indifferent_access + } + let(:namespace){ create(:namespace) } + + it 'creates project' do + allow_any_instance_of(Project).to receive(:add_import_job) + + project_creator = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, user) + project = project_creator.execute + + expect(project.import_url).to eq("https://oauth2:asdffg@gitlab.com/asd/vim.git") + expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE) + end +end diff --git a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb index 540618a5603..ab613193f41 100644 --- a/spec/lib/gitlab/gitlab_markdown_helper_spec.rb +++ b/spec/lib/gitlab/gitlab_markdown_helper_spec.rb @@ -5,24 +5,24 @@ describe Gitlab::MarkdownHelper do %w(textile rdoc org creole wiki mediawiki rst adoc asciidoc asc).each do |type| it "returns true for #{type} files" do - Gitlab::MarkdownHelper.markup?("README.#{type}").should be_true + expect(Gitlab::MarkdownHelper.markup?("README.#{type}")).to be_truthy end end it 'returns false when given a non-markup filename' do - Gitlab::MarkdownHelper.markup?('README.rb').should_not be_true + expect(Gitlab::MarkdownHelper.markup?('README.rb')).not_to be_truthy end end describe '#gitlab_markdown?' do %w(mdown md markdown).each do |type| it "returns true for #{type} files" do - Gitlab::MarkdownHelper.gitlab_markdown?("README.#{type}").should be_true + expect(Gitlab::MarkdownHelper.gitlab_markdown?("README.#{type}")).to be_truthy end end it 'returns false when given a non-markdown filename' do - Gitlab::MarkdownHelper.gitlab_markdown?('README.rb').should_not be_true + expect(Gitlab::MarkdownHelper.gitlab_markdown?('README.rb')).not_to be_truthy end end end diff --git a/spec/lib/gitlab/gitorious_import/project_creator.rb b/spec/lib/gitlab/gitorious_import/project_creator.rb new file mode 100644 index 00000000000..cf2318bb3a2 --- /dev/null +++ b/spec/lib/gitlab/gitorious_import/project_creator.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +describe Gitlab::GitoriousImport::ProjectCreator do + let(:user) { create(:user) } + let(:repo) { Gitlab::GitoriousImport::Repository.new('foo/bar-baz-qux') } + let(:namespace){ create(:namespace) } + + it 'creates project' do + allow_any_instance_of(Project).to receive(:add_import_job) + + project_creator = Gitlab::GitoriousImport::ProjectCreator.new(repo, namespace, user) + project_creator.execute + project = Project.last + + expect(project.name).to eq("Bar Baz Qux") + expect(project.path).to eq("bar-baz-qux") + expect(project.namespace).to eq(namespace) + expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC) + expect(project.import_type).to eq("gitorious") + expect(project.import_source).to eq("foo/bar-baz-qux") + expect(project.import_url).to eq("https://gitorious.org/foo/bar-baz-qux.git") + end +end diff --git a/spec/lib/gitlab/ldap/access_spec.rb b/spec/lib/gitlab/ldap/access_spec.rb index d50f605e050..707a0521ab3 100644 --- a/spec/lib/gitlab/ldap/access_spec.rb +++ b/spec/lib/gitlab/ldap/access_spec.rb @@ -1,16 +1,16 @@ require 'spec_helper' describe Gitlab::LDAP::Access do - let(:access) { Gitlab::LDAP::Access.new } - let(:user) { create(:user) } + let(:access) { Gitlab::LDAP::Access.new user } + let(:user) { create(:omniauth_user) } describe :allowed? do - subject { access.allowed?(user) } + subject { access.allowed? } context 'when the user cannot be found' do before { Gitlab::LDAP::Person.stub(find_by_dn: nil) } - it { should be_false } + it { is_expected.to be_falsey } end context 'when the user is found' do @@ -19,28 +19,36 @@ describe Gitlab::LDAP::Access do context 'and the user is diabled via active directory' do before { Gitlab::LDAP::Person.stub(disabled_via_active_directory?: true) } - it { should be_false } - end - - context 'and has no disabled flag in active diretory' do - before { Gitlab::LDAP::Person.stub(disabled_via_active_directory?: false) } + it { is_expected.to be_falsey } - it { should be_true } + it "should block user in GitLab" do + access.allowed? + user.should be_blocked + end end context 'and has no disabled flag in active diretory' do - before { + before do + user.block + Gitlab::LDAP::Person.stub(disabled_via_active_directory?: false) - Gitlab.config.ldap['enabled'] = true - Gitlab.config.ldap['active_directory'] = false - } + end + + it { is_expected.to be_truthy } + + it "should unblock user in GitLab" do + access.allowed? + user.should_not be_blocked + end + end - after { - Gitlab.config.ldap['enabled'] = false - Gitlab.config.ldap['active_directory'] = true - } + context 'without ActiveDirectory enabled' do + before do + Gitlab::LDAP::Config.stub(enabled?: true) + Gitlab::LDAP::Config.any_instance.stub(active_directory: false) + end - it { should be_false } + it { is_expected.to be_truthy } end end end diff --git a/spec/lib/gitlab/ldap/adapter_spec.rb b/spec/lib/gitlab/ldap/adapter_spec.rb index c3f07334431..b609e4b38f2 100644 --- a/spec/lib/gitlab/ldap/adapter_spec.rb +++ b/spec/lib/gitlab/ldap/adapter_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Gitlab::LDAP::Adapter do - let(:adapter) { Gitlab::LDAP::Adapter.new } + let(:adapter) { Gitlab::LDAP::Adapter.new 'ldapmain' } describe :dn_matches_filter? do let(:ldap) { double(:ldap) } @@ -12,20 +12,20 @@ describe Gitlab::LDAP::Adapter do context "and the result is non-empty" do before { ldap.stub(search: [:foo]) } - it { should be_true } + it { is_expected.to be_truthy } end context "and the result is empty" do before { ldap.stub(search: []) } - it { should be_false } + it { is_expected.to be_falsey } end end context "when the search encounters an error" do before { ldap.stub(search: nil, get_operation_result: double(code: 1, message: 'some error')) } - it { should be_false } + it { is_expected.to be_falsey } end end end diff --git a/spec/lib/gitlab/ldap/authentication_spec.rb b/spec/lib/gitlab/ldap/authentication_spec.rb new file mode 100644 index 00000000000..8afc2b21f46 --- /dev/null +++ b/spec/lib/gitlab/ldap/authentication_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Gitlab::LDAP::Authentication do + let(:klass) { Gitlab::LDAP::Authentication } + let(:user) { create(:omniauth_user, extern_uid: dn) } + let(:dn) { 'uid=john,ou=people,dc=example,dc=com' } + let(:login) { 'john' } + let(:password) { 'password' } + + describe :login do + let(:adapter) { double :adapter } + before do + Gitlab::LDAP::Config.stub(enabled?: true) + end + + it "finds the user if authentication is successful" do + user + # try only to fake the LDAP call + klass.any_instance.stub(adapter: double(:adapter, + bind_as: double(:ldap_user, dn: dn) + )) + expect(klass.login(login, password)).to be_truthy + end + + it "is false if the user does not exist" do + # try only to fake the LDAP call + klass.any_instance.stub(adapter: double(:adapter, + bind_as: double(:ldap_user, dn: dn) + )) + expect(klass.login(login, password)).to be_falsey + end + + it "is false if authentication fails" do + user + # try only to fake the LDAP call + klass.any_instance.stub(adapter: double(:adapter, bind_as: nil)) + expect(klass.login(login, password)).to be_falsey + end + + it "fails if ldap is disabled" do + Gitlab::LDAP::Config.stub(enabled?: false) + expect(klass.login(login, password)).to be_falsey + end + + it "fails if no login is supplied" do + expect(klass.login('', password)).to be_falsey + end + + it "fails if no password is supplied" do + expect(klass.login(login, '')).to be_falsey + end + end +end
\ No newline at end of file diff --git a/spec/lib/gitlab/ldap/config_spec.rb b/spec/lib/gitlab/ldap/config_spec.rb new file mode 100644 index 00000000000..2df2beca7a6 --- /dev/null +++ b/spec/lib/gitlab/ldap/config_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe Gitlab::LDAP::Config do + let(:config) { Gitlab::LDAP::Config.new provider } + let(:provider) { 'ldapmain' } + + describe '#initalize' do + it 'requires a provider' do + expect{ Gitlab::LDAP::Config.new }.to raise_error ArgumentError + end + + it "works" do + expect(config).to be_a described_class + end + + it "raises an error if a unknow provider is used" do + expect{ Gitlab::LDAP::Config.new 'unknown' }.to raise_error + end + + context "if 'ldap' is the provider name" do + let(:provider) { 'ldap' } + + context "and 'ldap' is not in defined as a provider" do + before { Gitlab::LDAP::Config.stub(providers: %w{ldapmain}) } + + it "uses the first provider" do + # Fetch the provider_name attribute from 'options' so that we know + # that the 'options' Hash is not empty/nil. + expect(config.options['provider_name']).to eq('ldapmain') + end + end + end + end +end diff --git a/spec/lib/gitlab/ldap/user_spec.rb b/spec/lib/gitlab/ldap/user_spec.rb index d232cb20759..4f93545feb6 100644 --- a/spec/lib/gitlab/ldap/user_spec.rb +++ b/spec/lib/gitlab/ldap/user_spec.rb @@ -1,54 +1,53 @@ require 'spec_helper' describe Gitlab::LDAP::User do - let(:gl_user) { Gitlab::LDAP::User } + let(:gl_user) { Gitlab::LDAP::User.new(auth_hash) } let(:info) do - double( + { name: 'John', email: 'john@example.com', nickname: 'john' - ) + } + end + let(:auth_hash) do + double(uid: 'my-uid', provider: 'ldapmain', info: double(info)) end - before { Gitlab.config.stub(omniauth: {}) } - describe :find_or_create do - let(:auth) do - double(info: info, provider: 'ldap', uid: 'my-uid') + describe :changed? do + it "marks existing ldap user as changed" do + existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_truthy end + it "marks existing non-ldap user if the email matches as changed" do + existing_user = create(:user, email: 'john@example.com') + expect(gl_user.changed?).to be_truthy + end + + it "dont marks existing ldap user as changed" do + existing_user = create(:omniauth_user, email: 'john@example.com', extern_uid: 'my-uid', provider: 'ldapmain') + expect(gl_user.changed?).to be_falsey + end + end + + describe :find_or_create do it "finds the user if already existing" do - existing_user = create(:user, extern_uid: 'my-uid', provider: 'ldap') + existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain') - expect{ gl_user.find_or_create(auth) }.to_not change{ User.count } + expect{ gl_user.save }.to_not change{ User.count } end it "connects to existing non-ldap user if the email matches" do - existing_user = create(:user, email: 'john@example.com') - expect{ gl_user.find_or_create(auth) }.to_not change{ User.count } + existing_user = create(:omniauth_user, email: 'john@example.com', provider: "twitter") + expect{ gl_user.save }.to_not change{ User.count } existing_user.reload - expect(existing_user.extern_uid).to eql 'my-uid' - expect(existing_user.provider).to eql 'ldap' + expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid' + expect(existing_user.ldap_identity.provider).to eql 'ldapmain' end it "creates a new user if not found" do - expect{ gl_user.find_or_create(auth) }.to change{ User.count }.by(1) - end - end - - describe "authenticate" do - let(:login) { 'john' } - let(:password) { 'my-secret' } - - before { - Gitlab.config.ldap['enabled'] = true - Gitlab.config.ldap['user_filter'] = 'employeeType=developer' - } - after { Gitlab.config.ldap['enabled'] = false } - - it "send an authentication request to ldap" do - expect( Gitlab::LDAP::User.adapter ).to receive(:bind_as) - Gitlab::LDAP::User.authenticate(login, password) + expect{ gl_user.save }.to change{ User.count }.by(1) end end end diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb new file mode 100644 index 00000000000..448cd0c6880 --- /dev/null +++ b/spec/lib/gitlab/note_data_builder_spec.rb @@ -0,0 +1,73 @@ +require 'spec_helper' + +describe 'Gitlab::NoteDataBuilder' do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:data) { Gitlab::NoteDataBuilder.build(note, user) } + let(:note_url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + let(:fixed_time) { Time.at(1425600000) } # Avoid time precision errors + + before(:each) do + expect(data).to have_key(:object_attributes) + expect(data[:object_attributes]).to have_key(:url) + expect(data[:object_attributes][:url]).to eq(note_url) + expect(data[:object_kind]).to eq('note') + expect(data[:user]).to eq(user.hook_attrs) + end + + describe 'When asking for a note on commit' do + let(:note) { create(:note_on_commit) } + + it 'returns the note and commit-specific data' do + expect(data).to have_key(:commit) + end + end + + describe 'When asking for a note on commit diff' do + let(:note) { create(:note_on_commit_diff) } + + it 'returns the note and commit-specific data' do + expect(data).to have_key(:commit) + end + end + + describe 'When asking for a note on issue' do + let(:issue) { create(:issue, created_at: fixed_time, updated_at: fixed_time) } + let(:note) { create(:note_on_issue, noteable_id: issue.id) } + + it 'returns the note and issue-specific data' do + expect(data).to have_key(:issue) + expect(data[:issue]).to eq(issue.hook_attrs) + end + end + + describe 'When asking for a note on merge request' do + let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) } + let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id) } + + it 'returns the note and merge request data' do + expect(data).to have_key(:merge_request) + expect(data[:merge_request]).to eq(merge_request.hook_attrs) + end + end + + describe 'When asking for a note on merge request diff' do + let(:merge_request) { create(:merge_request, created_at: fixed_time, updated_at: fixed_time) } + let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id) } + + it 'returns the note and merge request diff data' do + expect(data).to have_key(:merge_request) + expect(data[:merge_request]).to eq(merge_request.hook_attrs) + end + end + + describe 'When asking for a note on project snippet' do + let!(:snippet) { create(:project_snippet, created_at: fixed_time, updated_at: fixed_time) } + let!(:note) { create(:note_on_project_snippet, noteable_id: snippet.id) } + + it 'returns the note and project snippet data' do + expect(data).to have_key(:snippet) + expect(data[:snippet]).to eq(snippet.hook_attrs) + end + end +end diff --git a/spec/lib/gitlab/oauth/auth_hash_spec.rb b/spec/lib/gitlab/oauth/auth_hash_spec.rb new file mode 100644 index 00000000000..5eb77b492b2 --- /dev/null +++ b/spec/lib/gitlab/oauth/auth_hash_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' + +describe Gitlab::OAuth::AuthHash do + let(:auth_hash) do + Gitlab::OAuth::AuthHash.new(double({ + provider: 'twitter', + uid: uid, + info: double(info_hash) + })) + end + let(:uid) { 'my-uid' } + let(:email) { 'my-email@example.com' } + let(:nickname) { 'my-nickname' } + let(:info_hash) { + { + email: email, + nickname: nickname, + name: 'John', + first_name: "John", + last_name: "Who" + } + } + + context "defaults" do + it { expect(auth_hash.provider).to eql 'twitter' } + it { expect(auth_hash.uid).to eql uid } + it { expect(auth_hash.email).to eql email } + it { expect(auth_hash.username).to eql nickname } + it { expect(auth_hash.name).to eql "John" } + it { expect(auth_hash.password).to_not be_empty } + end + + context "email not provided" do + before { info_hash.delete(:email) } + it "generates a temp email" do + expect( auth_hash.email).to start_with('temp-email-for-oauth') + end + end + + context "username not provided" do + before { info_hash.delete(:nickname) } + + it "takes the first part of the email as username" do + expect( auth_hash.username ).to eql "my-email" + end + end + + context "name not provided" do + before { info_hash.delete(:name) } + + it "concats first and lastname as the name" do + expect( auth_hash.name ).to eql "John Who" + end + end +end
\ No newline at end of file diff --git a/spec/lib/gitlab/oauth/user_spec.rb b/spec/lib/gitlab/oauth/user_spec.rb index c241e198609..44cdd1e4fab 100644 --- a/spec/lib/gitlab/oauth/user_spec.rb +++ b/spec/lib/gitlab/oauth/user_spec.rb @@ -1,83 +1,109 @@ require 'spec_helper' describe Gitlab::OAuth::User do - let(:gl_auth) { Gitlab::OAuth::User } - let(:info) do - double( - nickname: 'john', + let(:oauth_user) { Gitlab::OAuth::User.new(auth_hash) } + let(:gl_user) { oauth_user.gl_user } + let(:uid) { 'my-uid' } + let(:provider) { 'my-provider' } + let(:auth_hash) { double(uid: uid, provider: provider, info: double(info_hash)) } + let(:info_hash) do + { + nickname: '-john+gitlab-ETC%.git@gmail.com', name: 'John', email: 'john@mail.com' - ) + } end - before do - Gitlab.config.stub(omniauth: {}) - end - - describe :find do - let!(:existing_user) { create(:user, extern_uid: 'my-uid', provider: 'my-provider') } + describe :persisted? do + let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') } it "finds an existing user based on uid and provider (facebook)" do auth = double(info: double(name: 'John'), uid: 'my-uid', provider: 'my-provider') - assert gl_auth.find(auth) + expect( oauth_user.persisted? ).to be_truthy end - it "finds an existing user based on nested uid and provider" do - auth = double(info: info, uid: 'my-uid', provider: 'my-provider') - assert gl_auth.find(auth) + it "returns false if use is not found in database" do + auth_hash.stub(uid: 'non-existing') + expect( oauth_user.persisted? ).to be_falsey end end - describe :create do - it "should create user from LDAP" do - auth = double(info: info, uid: 'my-uid', provider: 'ldap') - user = gl_auth.create(auth) + describe :save do + let(:provider) { 'twitter' } - user.should be_valid - user.extern_uid.should == auth.uid - user.provider.should == 'ldap' - end + describe 'signup' do + context "with allow_single_sign_on enabled" do + before { Gitlab.config.omniauth.stub allow_single_sign_on: true } - it "should create user from Omniauth" do - auth = double(info: info, uid: 'my-uid', provider: 'twitter') - user = gl_auth.create(auth) + it "creates a user from Omniauth" do + oauth_user.save - user.should be_valid - user.extern_uid.should == auth.uid - user.provider.should == 'twitter' + expect(gl_user).to be_valid + identity = gl_user.identities.first + expect(identity.extern_uid).to eql uid + expect(identity.provider).to eql 'twitter' + end + end + + context "with allow_single_sign_on disabled (Default)" do + it "throws an error" do + expect{ oauth_user.save }.to raise_error StandardError + end + end end - it "should apply defaults to user" do - auth = double(info: info, uid: 'my-uid', provider: 'ldap') - user = gl_auth.create(auth) + describe 'blocking' do + let(:provider) { 'twitter' } + before { Gitlab.config.omniauth.stub allow_single_sign_on: true } - user.should be_valid - user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit - user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group - end + context 'signup' do + context 'dont block on create' do + before { Gitlab.config.omniauth.stub block_auto_created_users: false } - it "Set a temp email address if not provided (like twitter does)" do - info = double( - uid: 'my-uid', - nickname: 'john', - name: 'John' - ) - auth = double(info: info, uid: 'my-uid', provider: 'my-provider') + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end - user = gl_auth.create(auth) - expect(user.email).to_not be_empty - end + context 'block on create' do + before { Gitlab.config.omniauth.stub block_auto_created_users: true } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).to be_blocked + end + end + end + + context 'sign-in' do + before do + oauth_user.save + oauth_user.gl_user.activate + end + + context 'dont block on create' do + before { Gitlab.config.omniauth.stub block_auto_created_users: false } + + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end - it 'generates a username if non provided (google)' do - info = double( - uid: 'my-uid', - name: 'John', - email: 'john@example.com' - ) - auth = double(info: info, uid: 'my-uid', provider: 'my-provider') + context 'block on create' do + before { Gitlab.config.omniauth.stub block_auto_created_users: true } - user = gl_auth.create(auth) - expect(user.username).to eql 'john' + it do + oauth_user.save + expect(gl_user).to be_valid + expect(gl_user).not_to be_blocked + end + end + end end end end diff --git a/spec/lib/gitlab/popen_spec.rb b/spec/lib/gitlab/popen_spec.rb index 76d506eb3c0..cd9d0456b25 100644 --- a/spec/lib/gitlab/popen_spec.rb +++ b/spec/lib/gitlab/popen_spec.rb @@ -13,8 +13,8 @@ describe 'Gitlab::Popen', no_db: true do @output, @status = @klass.new.popen(%W(ls), path) end - it { @status.should be_zero } - it { @output.should include('cache') } + it { expect(@status).to be_zero } + it { expect(@output).to include('cache') } end context 'non-zero status' do @@ -22,8 +22,8 @@ describe 'Gitlab::Popen', no_db: true do @output, @status = @klass.new.popen(%W(cat NOTHING), path) end - it { @status.should == 1 } - it { @output.should include('No such file or directory') } + it { expect(@status).to eq(1) } + it { expect(@output).to include('No such file or directory') } end context 'unsafe string command' do @@ -37,8 +37,8 @@ describe 'Gitlab::Popen', no_db: true do @output, @status = @klass.new.popen(%W(ls)) end - it { @status.should be_zero } - it { @output.should include('spec') } + it { expect(@status).to be_zero } + it { expect(@output).to include('spec') } end end diff --git a/spec/lib/gitlab/push_data_builder_spec.rb b/spec/lib/gitlab/push_data_builder_spec.rb new file mode 100644 index 00000000000..1b8ba7b4d43 --- /dev/null +++ b/spec/lib/gitlab/push_data_builder_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper' + +describe 'Gitlab::PushDataBuilder' do + let(:project) { create(:project) } + let(:user) { create(:user) } + + + describe :build_sample do + let(:data) { Gitlab::PushDataBuilder.build_sample(project, user) } + + it { expect(data).to be_a(Hash) } + it { expect(data[:before]).to eq('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') } + it { expect(data[:after]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } + it { expect(data[:ref]).to eq('refs/heads/master') } + it { expect(data[:commits].size).to eq(3) } + it { expect(data[:repository][:git_http_url]).to eq(project.http_url_to_repo) } + it { expect(data[:repository][:git_ssh_url]).to eq(project.ssh_url_to_repo) } + it { expect(data[:repository][:visibility_level]).to eq(project.visibility_level) } + it { expect(data[:total_commits_count]).to eq(3) } + end + + describe :build do + let(:data) do + Gitlab::PushDataBuilder.build(project, + user, + Gitlab::Git::BLANK_SHA, + '8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b', + 'refs/tags/v1.1.0') + end + + it { expect(data).to be_a(Hash) } + it { expect(data[:before]).to eq(Gitlab::Git::BLANK_SHA) } + it { expect(data[:checkout_sha]).to eq('5937ac0a7beb003549fc5fd26fc247adbce4a52e') } + it { expect(data[:after]).to eq('8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b') } + it { expect(data[:ref]).to eq('refs/tags/v1.1.0') } + it { expect(data[:commits]).to be_empty } + it { expect(data[:total_commits_count]).to be_zero } + end +end diff --git a/spec/lib/gitlab/reference_extractor_spec.rb b/spec/lib/gitlab/reference_extractor_spec.rb index 23867df39dd..034f8ee7c45 100644 --- a/spec/lib/gitlab/reference_extractor_spec.rb +++ b/spec/lib/gitlab/reference_extractor_spec.rb @@ -3,52 +3,56 @@ require 'spec_helper' describe Gitlab::ReferenceExtractor do it 'extracts username references' do subject.analyze('this contains a @user reference', nil) - subject.users.should == [{ project: nil, id: 'user' }] + expect(subject.users).to eq([{ project: nil, id: 'user' }]) end it 'extracts issue references' do subject.analyze('this one talks about issue #1234', nil) - subject.issues.should == [{ project: nil, id: '1234' }] + expect(subject.issues).to eq([{ project: nil, id: '1234' }]) end it 'extracts JIRA issue references' do - Gitlab.config.gitlab.stub(:issues_tracker).and_return('jira') subject.analyze('this one talks about issue JIRA-1234', nil) - subject.issues.should == [{ project: nil, id: 'JIRA-1234' }] + expect(subject.issues).to eq([{ project: nil, id: 'JIRA-1234' }]) end it 'extracts merge request references' do subject.analyze("and here's !43, a merge request", nil) - subject.merge_requests.should == [{ project: nil, id: '43' }] + expect(subject.merge_requests).to eq([{ project: nil, id: '43' }]) end it 'extracts snippet ids' do subject.analyze('snippets like $12 get extracted as well', nil) - subject.snippets.should == [{ project: nil, id: '12' }] + expect(subject.snippets).to eq([{ project: nil, id: '12' }]) end it 'extracts commit shas' do subject.analyze('commit shas 98cf0ae3 are pulled out as Strings', nil) - subject.commits.should == [{ project: nil, id: '98cf0ae3' }] + expect(subject.commits).to eq([{ project: nil, id: '98cf0ae3' }]) + end + + it 'extracts commit ranges' do + subject.analyze('here you go, a commit range: 98cf0ae3...98cf0ae4', nil) + expect(subject.commit_ranges).to eq([{ project: nil, id: '98cf0ae3...98cf0ae4' }]) end it 'extracts multiple references and preserves their order' do subject.analyze('@me and @you both care about this', nil) - subject.users.should == [ + expect(subject.users).to eq([ { project: nil, id: 'me' }, { project: nil, id: 'you' } - ] + ]) end it 'leaves the original note unmodified' do text = 'issue #123 is just the worst, @user' subject.analyze(text, nil) - text.should == 'issue #123 is just the worst, @user' + expect(text).to eq('issue #123 is just the worst, @user') end it 'handles all possible kinds of references' do accessors = Gitlab::Markdown::TYPES.map { |t| "#{t}s".to_sym } - subject.should respond_to(*accessors) + expect(subject).to respond_to(*accessors) end context 'with a project' do @@ -63,7 +67,7 @@ describe Gitlab::ReferenceExtractor do project.team << [@u_bar, :guest] subject.analyze('@foo, @baduser, @bar, and @offteam', project) - subject.users_for(project).should == [@u_foo, @u_bar] + expect(subject.users_for(project)).to eq([@u_foo, @u_bar]) end it 'accesses valid issue objects' do @@ -71,7 +75,7 @@ describe Gitlab::ReferenceExtractor do @i1 = create(:issue, project: project) subject.analyze("##{@i0.iid}, ##{@i1.iid}, and #999.", project) - subject.issues_for(project).should == [@i0, @i1] + expect(subject.issues_for(project)).to eq([@i0, @i1]) end it 'accesses valid merge requests' do @@ -79,7 +83,7 @@ describe Gitlab::ReferenceExtractor do @m1 = create(:merge_request, source_project: project, target_project: project, source_branch: 'bbb') subject.analyze("!999, !#{@m1.iid}, and !#{@m0.iid}.", project) - subject.merge_requests_for(project).should == [@m1, @m0] + expect(subject.merge_requests_for(project)).to eq([@m1, @m0]) end it 'accesses valid snippets' do @@ -88,7 +92,7 @@ describe Gitlab::ReferenceExtractor do @s2 = create(:project_snippet) subject.analyze("$#{@s0.id}, $999, $#{@s2.id}, $#{@s1.id}", project) - subject.snippets_for(project).should == [@s0, @s1] + expect(subject.snippets_for(project)).to eq([@s0, @s1]) end it 'accesses valid commits' do @@ -97,9 +101,23 @@ describe Gitlab::ReferenceExtractor do subject.analyze("this references commits #{commit.sha[0..6]} and 012345", project) extracted = subject.commits_for(project) - extracted.should have(1).item - extracted[0].sha.should == commit.sha - extracted[0].message.should == commit.message + expect(extracted.size).to eq(1) + expect(extracted[0].sha).to eq(commit.sha) + expect(extracted[0].message).to eq(commit.message) + end + + it 'accesses valid commit ranges' do + commit = project.repository.commit('master') + earlier_commit = project.repository.commit('master~2') + + subject.analyze("this references commits #{earlier_commit.sha[0..6]}...#{commit.sha[0..6]}", + project) + extracted = subject.commit_ranges_for(project) + expect(extracted.size).to eq(1) + expect(extracted[0][0].sha).to eq(earlier_commit.sha) + expect(extracted[0][0].message).to eq(earlier_commit.message) + expect(extracted[0][1].sha).to eq(commit.sha) + expect(extracted[0][1].message).to eq(commit.message) end end end diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb index a3aae7771bd..1db9f15b790 100644 --- a/spec/lib/gitlab/regex_spec.rb +++ b/spec/lib/gitlab/regex_spec.rb @@ -2,20 +2,20 @@ require 'spec_helper' describe Gitlab::Regex do describe 'path regex' do - it { 'gitlab-ce'.should match(Gitlab::Regex.path_regex) } - it { 'gitlab_git'.should match(Gitlab::Regex.path_regex) } - it { '_underscore.js'.should match(Gitlab::Regex.path_regex) } - it { '100px.com'.should match(Gitlab::Regex.path_regex) } - it { '?gitlab'.should_not match(Gitlab::Regex.path_regex) } - it { 'git lab'.should_not match(Gitlab::Regex.path_regex) } - it { 'gitlab.git'.should_not match(Gitlab::Regex.path_regex) } + it { expect('gitlab-ce').to match(Gitlab::Regex.path_regex) } + it { expect('gitlab_git').to match(Gitlab::Regex.path_regex) } + it { expect('_underscore.js').to match(Gitlab::Regex.path_regex) } + it { expect('100px.com').to match(Gitlab::Regex.path_regex) } + it { expect('?gitlab').not_to match(Gitlab::Regex.path_regex) } + it { expect('git lab').not_to match(Gitlab::Regex.path_regex) } + it { expect('gitlab.git').not_to match(Gitlab::Regex.path_regex) } end describe 'project name regex' do - it { 'gitlab-ce'.should match(Gitlab::Regex.project_name_regex) } - it { 'GitLab CE'.should match(Gitlab::Regex.project_name_regex) } - it { '100 lines'.should match(Gitlab::Regex.project_name_regex) } - it { 'gitlab.git'.should match(Gitlab::Regex.project_name_regex) } - it { '?gitlab'.should_not match(Gitlab::Regex.project_name_regex) } + it { expect('gitlab-ce').to match(Gitlab::Regex.project_name_regex) } + it { expect('GitLab CE').to match(Gitlab::Regex.project_name_regex) } + it { expect('100 lines').to match(Gitlab::Regex.project_name_regex) } + it { expect('gitlab.git').to match(Gitlab::Regex.project_name_regex) } + it { expect('?gitlab').not_to match(Gitlab::Regex.project_name_regex) } end end diff --git a/spec/lib/gitlab/satellite/action_spec.rb b/spec/lib/gitlab/satellite/action_spec.rb index 3eb1258d67e..28e3d64ee2b 100644 --- a/spec/lib/gitlab/satellite/action_spec.rb +++ b/spec/lib/gitlab/satellite/action_spec.rb @@ -6,7 +6,7 @@ describe 'Gitlab::Satellite::Action' do describe '#prepare_satellite!' do it 'should be able to fetch timeout from conf' do - Gitlab::Satellite::Action::DEFAULT_OPTIONS[:git_timeout].should == 30.seconds + expect(Gitlab::Satellite::Action::DEFAULT_OPTIONS[:git_timeout]).to eq(30.seconds) end it 'create a repository with a parking branch and one remote: origin' do @@ -15,22 +15,22 @@ describe 'Gitlab::Satellite::Action' do #now lets dirty it up starting_remote_count = repo.git.list_remotes.size - starting_remote_count.should >= 1 + expect(starting_remote_count).to be >= 1 #kind of hookey way to add a second remote origin_uri = repo.git.remote({v: true}).split(" ")[1] begin repo.git.remote({raise: true}, 'add', 'another-remote', origin_uri) repo.git.branch({raise: true}, 'a-new-branch') - repo.heads.size.should > (starting_remote_count) - repo.git.remote().split(" ").size.should > (starting_remote_count) + expect(repo.heads.size).to be > (starting_remote_count) + expect(repo.git.remote().split(" ").size).to be > (starting_remote_count) rescue end repo.git.config({}, "user.name", "#{user.name} -- foo") repo.git.config({}, "user.email", "#{user.email} -- foo") - repo.config['user.name'].should =="#{user.name} -- foo" - repo.config['user.email'].should =="#{user.email} -- foo" + expect(repo.config['user.name']).to eq("#{user.name} -- foo") + expect(repo.config['user.email']).to eq("#{user.email} -- foo") #These must happen in the context of the satellite directory... @@ -42,13 +42,13 @@ describe 'Gitlab::Satellite::Action' do #verify it's clean heads = repo.heads.map(&:name) - heads.size.should == 1 - heads.include?(Gitlab::Satellite::Satellite::PARKING_BRANCH).should == true + expect(heads.size).to eq(1) + expect(heads.include?(Gitlab::Satellite::Satellite::PARKING_BRANCH)).to eq(true) remotes = repo.git.remote().split(' ') - remotes.size.should == 1 - remotes.include?('origin').should == true - repo.config['user.name'].should ==user.name - repo.config['user.email'].should ==user.email + expect(remotes.size).to eq(1) + expect(remotes.include?('origin')).to eq(true) + expect(repo.config['user.name']).to eq(user.name) + expect(repo.config['user.email']).to eq(user.email) end end @@ -61,16 +61,16 @@ describe 'Gitlab::Satellite::Action' do #set assumptions FileUtils.rm_f(project.satellite.lock_file) - File.exists?(project.satellite.lock_file).should be_false + expect(File.exists?(project.satellite.lock_file)).to be_falsey satellite_action = Gitlab::Satellite::Action.new(user, project) satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo| - repo.should == sat_repo - (File.exists? project.satellite.lock_file).should be_true + expect(repo).to eq(sat_repo) + expect(File.exists? project.satellite.lock_file).to be_truthy called = true end - called.should be_true + expect(called).to be_truthy end @@ -80,19 +80,19 @@ describe 'Gitlab::Satellite::Action' do # Set base assumptions if File.exists? project.satellite.lock_file - FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false + expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey end satellite_action = Gitlab::Satellite::Action.new(user, project) satellite_action.send(:in_locked_and_timed_satellite) do |sat_repo| called = true - repo.should == sat_repo - (File.exists? project.satellite.lock_file).should be_true - FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_true + expect(repo).to eq(sat_repo) + expect(File.exists? project.satellite.lock_file).to be_truthy + expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_truthy end - called.should be_true - FileLockStatusChecker.new(project.satellite.lock_file).flocked?.should be_false + expect(called).to be_truthy + expect(FileLockStatusChecker.new(project.satellite.lock_file).flocked?).to be_falsey end diff --git a/spec/lib/gitlab/satellite/merge_action_spec.rb b/spec/lib/gitlab/satellite/merge_action_spec.rb index 479a73a1081..915e3ff0e51 100644 --- a/spec/lib/gitlab/satellite/merge_action_spec.rb +++ b/spec/lib/gitlab/satellite/merge_action_spec.rb @@ -13,9 +13,9 @@ describe 'Gitlab::Satellite::MergeAction' do describe '#commits_between' do def verify_commits(commits, first_commit_sha, last_commit_sha) - commits.each { |commit| commit.class.should == Gitlab::Git::Commit } - commits.first.id.should == first_commit_sha - commits.last.id.should == last_commit_sha + commits.each { |commit| expect(commit.class).to eq(Gitlab::Git::Commit) } + expect(commits.first.id).to eq(first_commit_sha) + expect(commits.last.id).to eq(last_commit_sha) end context 'on fork' do @@ -35,7 +35,7 @@ describe 'Gitlab::Satellite::MergeAction' do describe '#format_patch' do def verify_content(patch) sample_compare.commits.each do |commit| - patch.include?(commit).should be_true + expect(patch.include?(commit)).to be_truthy end end @@ -57,11 +57,11 @@ describe 'Gitlab::Satellite::MergeAction' do describe '#diffs_between_satellite tested against diff_in_satellite' do def is_a_matching_diff(diff, diffs) diff_count = diff.scan('diff --git').size - diff_count.should >= 1 - diffs.size.should == diff_count + expect(diff_count).to be >= 1 + expect(diffs.size).to eq(diff_count) diffs.each do |a_diff| - a_diff.class.should == Gitlab::Git::Diff - (diff.include? a_diff.diff).should be_true + expect(a_diff.class).to eq(Gitlab::Git::Diff) + expect(diff.include? a_diff.diff).to be_truthy end end @@ -82,23 +82,23 @@ describe 'Gitlab::Satellite::MergeAction' do describe '#can_be_merged?' do context 'on fork' do - it { Gitlab::Satellite::MergeAction.new( + it { expect(Gitlab::Satellite::MergeAction.new( merge_request_fork.author, - merge_request_fork).can_be_merged?.should be_true } + merge_request_fork).can_be_merged?).to be_truthy } - it { Gitlab::Satellite::MergeAction.new( + it { expect(Gitlab::Satellite::MergeAction.new( merge_request_fork_with_conflict.author, - merge_request_fork_with_conflict).can_be_merged?.should be_false } + merge_request_fork_with_conflict).can_be_merged?).to be_falsey } end context 'between branches' do - it { Gitlab::Satellite::MergeAction.new( + it { expect(Gitlab::Satellite::MergeAction.new( merge_request.author, - merge_request).can_be_merged?.should be_true } + merge_request).can_be_merged?).to be_truthy } - it { Gitlab::Satellite::MergeAction.new( + it { expect(Gitlab::Satellite::MergeAction.new( merge_request_with_conflict.author, - merge_request_with_conflict).can_be_merged?.should be_false } + merge_request_with_conflict).can_be_merged?).to be_falsey } end end end diff --git a/spec/lib/gitlab/upgrader_spec.rb b/spec/lib/gitlab/upgrader_spec.rb index 2b254d6b3a6..ce3ea6c260a 100644 --- a/spec/lib/gitlab/upgrader_spec.rb +++ b/spec/lib/gitlab/upgrader_spec.rb @@ -5,20 +5,20 @@ describe Gitlab::Upgrader do let(:current_version) { Gitlab::VERSION } describe 'current_version_raw' do - it { upgrader.current_version_raw.should == current_version } + it { expect(upgrader.current_version_raw).to eq(current_version) } end describe 'latest_version?' do it 'should be true if newest version' do upgrader.stub(latest_version_raw: current_version) - upgrader.latest_version?.should be_true + expect(upgrader.latest_version?).to be_truthy end end describe 'latest_version_raw' do it 'should be latest version for GitLab 5' do upgrader.stub(current_version_raw: "5.3.0") - upgrader.latest_version_raw.should == "v5.4.2" + expect(upgrader.latest_version_raw).to eq("v5.4.2") end end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index eb47bee8336..5153ed15af3 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -5,7 +5,73 @@ describe Gitlab::UrlBuilder do it 'returns the issue url' do issue = create(:issue) url = Gitlab::UrlBuilder.new(:issue).build(issue.id) - expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.to_param}/issues/#{issue.iid}" + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}" + end + end + + describe 'When asking for an merge request' do + it 'returns the merge request url' do + merge_request = create(:merge_request) + url = Gitlab::UrlBuilder.new(:merge_request).build(merge_request.id) + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}" + end + end + + describe 'When asking for a note on commit' do + let(:note) { create(:note_on_commit) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end + + describe 'When asking for a note on commit diff' do + let(:note) { create(:note_on_commit_diff) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{note.project.path_with_namespace}/commit/#{note.commit_id}#note_#{note.id}" + end + end + + describe 'When asking for a note on issue' do + let(:issue) { create(:issue) } + let(:note) { create(:note_on_issue, noteable_id: issue.id) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{issue.project.path_with_namespace}/issues/#{issue.iid}#note_#{note.id}" + end + end + + describe 'When asking for a note on merge request' do + let(:merge_request) { create(:merge_request) } + let(:note) { create(:note_on_merge_request, noteable_id: merge_request.id) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + describe 'When asking for a note on merge request diff' do + let(:merge_request) { create(:merge_request) } + let(:note) { create(:note_on_merge_request_diff, noteable_id: merge_request.id) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{merge_request.project.path_with_namespace}/merge_requests/#{merge_request.iid}#note_#{note.id}" + end + end + + describe 'When asking for a note on project snippet' do + let(:snippet) { create(:project_snippet) } + let(:note) { create(:note_on_project_snippet, noteable_id: snippet.id) } + let(:url) { Gitlab::UrlBuilder.new(:note).build(note.id) } + + it 'returns the note url' do + expect(url).to eq "#{Settings.gitlab['url']}/#{snippet.project.path_with_namespace}/snippets/#{note.noteable_id}#note_#{note.id}" end end end diff --git a/spec/lib/gitlab/version_info_spec.rb b/spec/lib/gitlab/version_info_spec.rb index 94dccf7a4e5..5afeb1c1ec3 100644 --- a/spec/lib/gitlab/version_info_spec.rb +++ b/spec/lib/gitlab/version_info_spec.rb @@ -12,58 +12,58 @@ describe 'Gitlab::VersionInfo', no_db: true do end context '>' do - it { @v2_0_0.should > @v1_1_0 } - it { @v1_1_0.should > @v1_0_1 } - it { @v1_0_1.should > @v1_0_0 } - it { @v1_0_0.should > @v0_1_0 } - it { @v0_1_0.should > @v0_0_1 } + it { expect(@v2_0_0).to be > @v1_1_0 } + it { expect(@v1_1_0).to be > @v1_0_1 } + it { expect(@v1_0_1).to be > @v1_0_0 } + it { expect(@v1_0_0).to be > @v0_1_0 } + it { expect(@v0_1_0).to be > @v0_0_1 } end context '>=' do - it { @v2_0_0.should >= Gitlab::VersionInfo.new(2, 0, 0) } - it { @v2_0_0.should >= @v1_1_0 } + it { expect(@v2_0_0).to be >= Gitlab::VersionInfo.new(2, 0, 0) } + it { expect(@v2_0_0).to be >= @v1_1_0 } end context '<' do - it { @v0_0_1.should < @v0_1_0 } - it { @v0_1_0.should < @v1_0_0 } - it { @v1_0_0.should < @v1_0_1 } - it { @v1_0_1.should < @v1_1_0 } - it { @v1_1_0.should < @v2_0_0 } + it { expect(@v0_0_1).to be < @v0_1_0 } + it { expect(@v0_1_0).to be < @v1_0_0 } + it { expect(@v1_0_0).to be < @v1_0_1 } + it { expect(@v1_0_1).to be < @v1_1_0 } + it { expect(@v1_1_0).to be < @v2_0_0 } end context '<=' do - it { @v0_0_1.should <= Gitlab::VersionInfo.new(0, 0, 1) } - it { @v0_0_1.should <= @v0_1_0 } + it { expect(@v0_0_1).to be <= Gitlab::VersionInfo.new(0, 0, 1) } + it { expect(@v0_0_1).to be <= @v0_1_0 } end context '==' do - it { @v0_0_1.should == Gitlab::VersionInfo.new(0, 0, 1) } - it { @v0_1_0.should == Gitlab::VersionInfo.new(0, 1, 0) } - it { @v1_0_0.should == Gitlab::VersionInfo.new(1, 0, 0) } + it { expect(@v0_0_1).to eq(Gitlab::VersionInfo.new(0, 0, 1)) } + it { expect(@v0_1_0).to eq(Gitlab::VersionInfo.new(0, 1, 0)) } + it { expect(@v1_0_0).to eq(Gitlab::VersionInfo.new(1, 0, 0)) } end context '!=' do - it { @v0_0_1.should_not == @v0_1_0 } + it { expect(@v0_0_1).not_to eq(@v0_1_0) } end context 'unknown' do - it { @unknown.should_not be @v0_0_1 } - it { @unknown.should_not be Gitlab::VersionInfo.new } + it { expect(@unknown).not_to be @v0_0_1 } + it { expect(@unknown).not_to be Gitlab::VersionInfo.new } it { expect{@unknown > @v0_0_1}.to raise_error(ArgumentError) } it { expect{@unknown < @v0_0_1}.to raise_error(ArgumentError) } end context 'parse' do - it { Gitlab::VersionInfo.parse("1.0.0").should == @v1_0_0 } - it { Gitlab::VersionInfo.parse("1.0.0.1").should == @v1_0_0 } - it { Gitlab::VersionInfo.parse("git 1.0.0b1").should == @v1_0_0 } - it { Gitlab::VersionInfo.parse("git 1.0b1").should_not be_valid } + it { expect(Gitlab::VersionInfo.parse("1.0.0")).to eq(@v1_0_0) } + it { expect(Gitlab::VersionInfo.parse("1.0.0.1")).to eq(@v1_0_0) } + it { expect(Gitlab::VersionInfo.parse("git 1.0.0b1")).to eq(@v1_0_0) } + it { expect(Gitlab::VersionInfo.parse("git 1.0b1")).not_to be_valid } end context 'to_s' do - it { @v1_0_0.to_s.should == "1.0.0" } - it { @unknown.to_s.should == "Unknown" } + it { expect(@v1_0_0.to_s).to eq("1.0.0") } + it { expect(@unknown.to_s).to eq("Unknown") } end end diff --git a/spec/lib/repository_cache_spec.rb b/spec/lib/repository_cache_spec.rb new file mode 100644 index 00000000000..af399f3a731 --- /dev/null +++ b/spec/lib/repository_cache_spec.rb @@ -0,0 +1,34 @@ +require 'rspec' +require_relative '../../lib/repository_cache' + +describe RepositoryCache do + let(:backend) { double('backend').as_null_object } + let(:cache) { RepositoryCache.new('example', backend) } + + describe '#cache_key' do + it 'includes the namespace' do + expect(cache.cache_key(:foo)).to eq 'foo:example' + end + end + + describe '#expire' do + it 'expires the given key from the cache' do + cache.expire(:foo) + expect(backend).to have_received(:delete).with('foo:example') + end + end + + describe '#fetch' do + it 'fetches the given key from the cache' do + cache.fetch(:bar) + expect(backend).to have_received(:fetch).with('bar:example') + end + + it 'accepts a block' do + p = -> {} + + cache.fetch(:baz, &p) + expect(backend).to have_received(:fetch).with('baz:example', &p) + end + end +end diff --git a/spec/lib/votes_spec.rb b/spec/lib/votes_spec.rb index a3c353d5eab..df243a26008 100644 --- a/spec/lib/votes_spec.rb +++ b/spec/lib/votes_spec.rb @@ -5,132 +5,181 @@ describe Issue, 'Votes' do describe "#upvotes" do it "with no notes has a 0/0 score" do - issue.upvotes.should == 0 + expect(issue.upvotes).to eq(0) end it "should recognize non-+1 notes" do add_note "No +1 here" - issue.should have(1).note - issue.notes.first.upvote?.should be_false - issue.upvotes.should == 0 + expect(issue.notes.size).to eq(1) + expect(issue.notes.first.upvote?).to be_falsey + expect(issue.upvotes).to eq(0) end it "should recognize a single +1 note" do add_note "+1 This is awesome" - issue.upvotes.should == 1 + expect(issue.upvotes).to eq(1) end - it "should recognize multiple +1 notes" do - add_note "+1 This is awesome" - add_note "+1 I want this" - issue.upvotes.should == 2 + it 'should recognize multiple +1 notes' do + add_note '+1 This is awesome', create(:user) + add_note '+1 I want this', create(:user) + expect(issue.upvotes).to eq(2) + end + + it 'should not count 2 +1 votes from the same user' do + add_note '+1 This is awesome' + add_note '+1 I want this' + expect(issue.upvotes).to eq(1) end end describe "#downvotes" do it "with no notes has a 0/0 score" do - issue.downvotes.should == 0 + expect(issue.downvotes).to eq(0) end it "should recognize non--1 notes" do add_note "Almost got a -1" - issue.should have(1).note - issue.notes.first.downvote?.should be_false - issue.downvotes.should == 0 + expect(issue.notes.size).to eq(1) + expect(issue.notes.first.downvote?).to be_falsey + expect(issue.downvotes).to eq(0) end it "should recognize a single -1 note" do add_note "-1 This is bad" - issue.downvotes.should == 1 + expect(issue.downvotes).to eq(1) end it "should recognize multiple -1 notes" do - add_note "-1 This is bad" - add_note "-1 Away with this" - issue.downvotes.should == 2 + add_note('-1 This is bad', create(:user)) + add_note('-1 Away with this', create(:user)) + expect(issue.downvotes).to eq(2) end end describe "#votes_count" do it "with no notes has a 0/0 score" do - issue.votes_count.should == 0 + expect(issue.votes_count).to eq(0) end it "should recognize non notes" do add_note "No +1 here" - issue.should have(1).note - issue.votes_count.should == 0 + expect(issue.notes.size).to eq(1) + expect(issue.votes_count).to eq(0) end it "should recognize a single +1 note" do add_note "+1 This is awesome" - issue.votes_count.should == 1 + expect(issue.votes_count).to eq(1) end it "should recognize a single -1 note" do add_note "-1 This is bad" - issue.votes_count.should == 1 + expect(issue.votes_count).to eq(1) end it "should recognize multiple notes" do - add_note "+1 This is awesome" - add_note "-1 This is bad" - add_note "+1 I want this" - issue.votes_count.should == 3 + add_note('+1 This is awesome', create(:user)) + add_note('-1 This is bad', create(:user)) + add_note('+1 I want this', create(:user)) + expect(issue.votes_count).to eq(3) + end + + it 'should not count 2 -1 votes from the same user' do + add_note '-1 This is suspicious' + add_note '-1 This is bad' + expect(issue.votes_count).to eq(1) end end describe "#upvotes_in_percent" do it "with no notes has a 0% score" do - issue.upvotes_in_percent.should == 0 + expect(issue.upvotes_in_percent).to eq(0) end it "should count a single 1 note as 100%" do add_note "+1 This is awesome" - issue.upvotes_in_percent.should == 100 + expect(issue.upvotes_in_percent).to eq(100) end - it "should count multiple +1 notes as 100%" do - add_note "+1 This is awesome" - add_note "+1 I want this" - issue.upvotes_in_percent.should == 100 + it 'should count multiple +1 notes as 100%' do + add_note('+1 This is awesome', create(:user)) + add_note('+1 I want this', create(:user)) + expect(issue.upvotes_in_percent).to eq(100) end - it "should count fractions for multiple +1 and -1 notes correctly" do - add_note "+1 This is awesome" - add_note "+1 I want this" - add_note "-1 This is bad" - add_note "+1 me too" - issue.upvotes_in_percent.should == 75 + it 'should count fractions for multiple +1 and -1 notes correctly' do + add_note('+1 This is awesome', create(:user)) + add_note('+1 I want this', create(:user)) + add_note('-1 This is bad', create(:user)) + add_note('+1 me too', create(:user)) + expect(issue.upvotes_in_percent).to eq(75) end end describe "#downvotes_in_percent" do it "with no notes has a 0% score" do - issue.downvotes_in_percent.should == 0 + expect(issue.downvotes_in_percent).to eq(0) end it "should count a single -1 note as 100%" do add_note "-1 This is bad" - issue.downvotes_in_percent.should == 100 + expect(issue.downvotes_in_percent).to eq(100) end - it "should count multiple -1 notes as 100%" do - add_note "-1 This is bad" - add_note "-1 Away with this" - issue.downvotes_in_percent.should == 100 + it 'should count multiple -1 notes as 100%' do + add_note('-1 This is bad', create(:user)) + add_note('-1 Away with this', create(:user)) + expect(issue.downvotes_in_percent).to eq(100) end - it "should count fractions for multiple +1 and -1 notes correctly" do - add_note "+1 This is awesome" - add_note "+1 I want this" - add_note "-1 This is bad" - add_note "+1 me too" - issue.downvotes_in_percent.should == 25 + it 'should count fractions for multiple +1 and -1 notes correctly' do + add_note('+1 This is awesome', create(:user)) + add_note('+1 I want this', create(:user)) + add_note('-1 This is bad', create(:user)) + add_note('+1 me too', create(:user)) + expect(issue.downvotes_in_percent).to eq(25) + end + end + + describe '#filter_superceded_votes' do + + it 'should count a users vote only once amongst multiple votes' do + add_note('-1 This needs work before I will accept it') + add_note('+1 I want this', create(:user)) + add_note('+1 This is is awesome', create(:user)) + add_note('+1 this looks good now') + add_note('+1 This is awesome', create(:user)) + add_note('+1 me too', create(:user)) + expect(issue.downvotes).to eq(0) + expect(issue.upvotes).to eq(5) end + + it 'should count each users vote only once' do + add_note '-1 This needs work before it will be accepted' + add_note '+1 I like this' + add_note '+1 I still like this' + add_note '+1 I really like this' + add_note '+1 Give me this now!!!!' + expect(issue.downvotes).to eq(0) + expect(issue.upvotes).to eq(1) + end + + it 'should count a users vote only once without caring about comments' do + add_note '-1 This needs work before it will be accepted' + add_note 'Comment 1' + add_note 'Another comment' + add_note '+1 vote' + add_note 'final comment' + expect(issue.downvotes).to eq(0) + expect(issue.upvotes).to eq(1) + end + end - def add_note(text) - issue.notes << create(:note, note: text, project: issue.project) + def add_note(text, author = issue.author) + created_at = Time.now - 1.hour + Note.count.seconds + issue.notes << create(:note, note: text, project: issue.project, + author_id: author.id, created_at: created_at) end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index e06e8826e5c..e3a3b542358 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -5,38 +5,46 @@ describe Notify do include EmailSpec::Matchers include RepoHelpers + let(:gitlab_sender_display_name) { Gitlab.config.gitlab.email_display_name } let(:gitlab_sender) { Gitlab.config.gitlab.email_from } let(:recipient) { create(:user, email: 'recipient@example.com') } let(:project) { create(:project) } + before(:each) do + email = recipient.emails.create(email: "notifications@example.com") + recipient.update_attribute(:notification_email, email.email) + end + shared_examples 'a multiple recipients email' do it 'is sent to the given recipient' do - should deliver_to recipient.email + is_expected.to deliver_to recipient.notification_email end end shared_examples 'an email sent from GitLab' do it 'is sent from GitLab' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq('GitLab') - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(gitlab_sender_display_name) + expect(sender.address).to eq(gitlab_sender) end end shared_examples 'an email starting a new thread' do |message_id_prefix| it 'has a discussion identifier' do - should have_header 'Message-ID', /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + is_expected.to have_header 'Message-ID', /<#{message_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ end end shared_examples 'an answer to an existing thread' do |thread_id_prefix| it 'has a subject that begins with Re: ' do - should have_subject /^Re: / + is_expected.to have_subject /^Re: / end it 'has headers that reference an existing thread' do - should have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ - should have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + is_expected.to have_header 'References', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + is_expected.to have_header 'In-Reply-To', /<#{thread_id_prefix}(.*)@#{Gitlab.config.gitlab.host}>/ + is_expected.to have_header 'X-GitLab-Project', /#{project.name}/ end end @@ -46,35 +54,35 @@ describe Notify do token = 'kETLwRaayvigPq_x3SNM' - subject { Notify.new_user_email(new_user.id, new_user.password, token) } + subject { Notify.new_user_email(new_user.id, token) } it_behaves_like 'an email sent from GitLab' it 'is sent to the new user' do - should deliver_to new_user.email + is_expected.to deliver_to new_user.email end it 'has the correct subject' do - should have_subject /^Account was created for you$/i + is_expected.to have_subject /^Account was created for you$/i end it 'contains the new user\'s login name' do - should have_body_text /#{new_user.email}/ + is_expected.to have_body_text /#{new_user.email}/ end it 'contains the password text' do - should have_body_text /Click here to set your password/ + is_expected.to have_body_text /Click here to set your password/ end it 'includes a link for user to set password' do params = "reset_password_token=#{token}" - should have_body_text( + is_expected.to have_body_text( %r{http://localhost(:\d+)?/users/password/edit\?#{params}} ) end it 'includes a link to the site' do - should have_body_text /#{example_site_path}/ + is_expected.to have_body_text /#{example_site_path}/ end end @@ -83,28 +91,28 @@ describe Notify do let(:example_site_path) { root_path } let(:new_user) { create(:user, email: 'newguy@example.com', password: "securePassword") } - subject { Notify.new_user_email(new_user.id, new_user.password) } + subject { Notify.new_user_email(new_user.id) } it_behaves_like 'an email sent from GitLab' it 'is sent to the new user' do - should deliver_to new_user.email + is_expected.to deliver_to new_user.email end it 'has the correct subject' do - should have_subject /^Account was created for you$/i + is_expected.to have_subject /^Account was created for you$/i end it 'contains the new user\'s login name' do - should have_body_text /#{new_user.email}/ + is_expected.to have_body_text /#{new_user.email}/ end it 'should not contain the new user\'s password' do - should_not have_body_text /password/ + is_expected.not_to have_body_text /password/ end it 'includes a link to the site' do - should have_body_text /#{example_site_path}/ + is_expected.to have_body_text /#{example_site_path}/ end end @@ -116,19 +124,19 @@ describe Notify do it_behaves_like 'an email sent from GitLab' it 'is sent to the new user' do - should deliver_to key.user.email + is_expected.to deliver_to key.user.email end it 'has the correct subject' do - should have_subject /^SSH key was added to your account$/i + is_expected.to have_subject /^SSH key was added to your account$/i end it 'contains the new ssh key title' do - should have_body_text /#{key.title}/ + is_expected.to have_body_text /#{key.title}/ end it 'includes a link to ssh keys page' do - should have_body_text /#{profile_keys_path}/ + is_expected.to have_body_text /#{profile_keys_path}/ end end @@ -138,19 +146,19 @@ describe Notify do subject { Notify.new_email_email(email.id) } it 'is sent to the new user' do - should deliver_to email.user.email + is_expected.to deliver_to email.user.email end it 'has the correct subject' do - should have_subject /^Email was added to your account$/i + is_expected.to have_subject /^Email was added to your account$/i end it 'contains the new email address' do - should have_body_text /#{email.email}/ + is_expected.to have_body_text /#{email.email}/ end it 'includes a link to emails page' do - should have_body_text /#{profile_emails_path}/ + is_expected.to have_body_text /#{profile_emails_path}/ end end @@ -163,18 +171,25 @@ describe Notify do shared_examples 'an assignee email' do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(current_user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(current_user.name) + expect(sender.address).to eq(gitlab_sender) end it 'is sent to the assignee' do - should deliver_to assignee.email + is_expected.to deliver_to assignee.email end end context 'for issues' do let(:issue) { create(:issue, author: current_user, assignee: assignee, project: project) } let(:issue_with_description) { create(:issue, author: current_user, assignee: assignee, project: project, description: Faker::Lorem.sentence) } + let(:issue_with_image) do + create(:issue, + author: current_user, + assignee: assignee, + project: project, + description: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)") + end describe 'that are new' do subject { Notify.new_issue_email(issue.assignee_id, issue.id) } @@ -183,11 +198,11 @@ describe Notify do it_behaves_like 'an email starting a new thread', 'issue' it 'has the correct subject' do - should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/ + is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/ end it 'contains a link to the new issue' do - should have_body_text /#{project_issue_path project, issue}/ + is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/ end end @@ -195,7 +210,23 @@ describe Notify do subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) } it 'contains the description' do - should have_body_text /#{issue_with_description.description}/ + is_expected.to have_body_text /#{issue_with_description.description}/ + end + end + + describe 'that contain images' do + let(:png) { File.read("#{Rails.root}/spec/fixtures/dk.png") } + let(:png_encoded) { Base64::encode64(png) } + + before :each do + file_path = File.join(Rails.root, 'public', 'uploads', issue_with_image.project.path_with_namespace, '12345/test.jpg') + allow(File).to receive(:file?).with(file_path).and_return(true) + allow(File).to receive(:read).with(file_path).and_return(png) + end + + subject { Notify.new_issue_email(issue_with_image.assignee_id, issue_with_image.id) } + it 'replaces attached images with inline images' do + is_expected.to have_body_text URI.encode(png_encoded) end end @@ -207,24 +238,24 @@ describe Notify do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(current_user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(current_user.name) + expect(sender.address).to eq(gitlab_sender) end it 'has the correct subject' do - should have_subject /#{issue.title} \(##{issue.iid}\)/ + is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/ end it 'contains the name of the previous assignee' do - should have_body_text /#{previous_assignee.name}/ + is_expected.to have_body_text /#{previous_assignee.name}/ end it 'contains the name of the new assignee' do - should have_body_text /#{assignee.name}/ + is_expected.to have_body_text /#{assignee.name}/ end it 'contains a link to the issue' do - should have_body_text /#{project_issue_path project, issue}/ + is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/ end end @@ -236,24 +267,24 @@ describe Notify do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(current_user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(current_user.name) + expect(sender.address).to eq(gitlab_sender) end it 'has the correct subject' do - should have_subject /#{issue.title} \(##{issue.iid}\)/i + is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/i end it 'contains the new status' do - should have_body_text /#{status}/i + is_expected.to have_body_text /#{status}/i end it 'contains the user name' do - should have_body_text /#{current_user.name}/i + is_expected.to have_body_text /#{current_user.name}/i end it 'contains a link to the issue' do - should have_body_text /#{project_issue_path project, issue}/ + is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/ end end @@ -263,6 +294,14 @@ describe Notify do let(:merge_author) { create(:user) } let(:merge_request) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project) } let(:merge_request_with_description) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project, description: Faker::Lorem.sentence) } + let(:merge_request_with_image) do + create(:merge_request, + author: current_user, + assignee: assignee, + source_project: project, + target_project: project, + description: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)") + end describe 'that are new' do subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) } @@ -271,23 +310,23 @@ describe Notify do it_behaves_like 'an email starting a new thread', 'merge_request' it 'has the correct subject' do - should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ + is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ end it 'contains a link to the new merge request' do - should have_body_text /#{project_merge_request_path(project, merge_request)}/ + is_expected.to have_body_text /#{namespace_project_merge_request_path(project.namespace, project, merge_request)}/ end it 'contains the source branch for the merge request' do - should have_body_text /#{merge_request.source_branch}/ + is_expected.to have_body_text /#{merge_request.source_branch}/ end it 'contains the target branch for the merge request' do - should have_body_text /#{merge_request.target_branch}/ + is_expected.to have_body_text /#{merge_request.target_branch}/ end it 'has the correct message-id set' do - should have_header 'Message-ID', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>" + is_expected.to have_header 'Message-ID', "<merge_request_#{merge_request.id}@#{Gitlab.config.gitlab.host}>" end end @@ -295,7 +334,23 @@ describe Notify do subject { Notify.new_merge_request_email(merge_request_with_description.assignee_id, merge_request_with_description.id) } it 'contains the description' do - should have_body_text /#{merge_request_with_description.description}/ + is_expected.to have_body_text /#{merge_request_with_description.description}/ + end + end + + describe 'that are new and contain contain images in the description' do + let(:png) {File.read("#{Rails.root}/spec/fixtures/dk.png")} + let(:png_encoded) { Base64::encode64(png) } + + before :each do + file_path = File.join(Rails.root, 'public', 'uploads', merge_request_with_image.project.path_with_namespace, '/12345/test.jpg') + allow(File).to receive(:file?).with(file_path).and_return(true) + allow(File).to receive(:read).with(file_path).and_return(png) + end + + subject { Notify.new_merge_request_email(merge_request_with_image.assignee_id, merge_request_with_image.id) } + it 'replaces attached images with inline images' do + is_expected.to have_body_text URI.encode(png_encoded) end end @@ -307,24 +362,24 @@ describe Notify do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(current_user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(current_user.name) + expect(sender.address).to eq(gitlab_sender) end it 'has the correct subject' do - should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ + is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ end it 'contains the name of the previous assignee' do - should have_body_text /#{previous_assignee.name}/ + is_expected.to have_body_text /#{previous_assignee.name}/ end it 'contains the name of the new assignee' do - should have_body_text /#{assignee.name}/ + is_expected.to have_body_text /#{assignee.name}/ end it 'contains a link to the merge request' do - should have_body_text /#{project_merge_request_path project, merge_request}/ + is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/ end end @@ -336,24 +391,24 @@ describe Notify do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(current_user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(current_user.name) + expect(sender.address).to eq(gitlab_sender) end it 'has the correct subject' do - should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/i + is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/i end it 'contains the new status' do - should have_body_text /#{status}/i + is_expected.to have_body_text /#{status}/i end it 'contains the user name' do - should have_body_text /#{current_user.name}/i + is_expected.to have_body_text /#{current_user.name}/i end it 'contains a link to the merge request' do - should have_body_text /#{project_merge_request_path project, merge_request}/ + is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/ end end @@ -365,20 +420,20 @@ describe Notify do it 'is sent as the merge author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(merge_author.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(merge_author.name) + expect(sender.address).to eq(gitlab_sender) end it 'has the correct subject' do - should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ + is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ end it 'contains the new status' do - should have_body_text /merged/i + is_expected.to have_body_text /merged/i end it 'contains a link to the merge request' do - should have_body_text /#{project_merge_request_path project, merge_request}/ + is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/ end end end @@ -392,36 +447,39 @@ describe Notify do it_behaves_like 'an email sent from GitLab' it 'has the correct subject' do - should have_subject /Project was moved/ + is_expected.to have_subject /Project was moved/ end it 'contains name of project' do - should have_body_text /#{project.name_with_namespace}/ + is_expected.to have_body_text /#{project.name_with_namespace}/ end it 'contains new user role' do - should have_body_text /#{project.ssh_url_to_repo}/ + is_expected.to have_body_text /#{project.ssh_url_to_repo}/ end end describe 'project access changed' do let(:project) { create(:project) } let(:user) { create(:user) } - let(:project_member) { create(:project_member, - project: project, - user: user) } + let(:project_member) do + create(:project_member, + project: project, + user: user) + end + subject { Notify.project_access_granted_email(project_member.id) } it_behaves_like 'an email sent from GitLab' it 'has the correct subject' do - should have_subject /Access to project was granted/ + is_expected.to have_subject /Access to project was granted/ end it 'contains name of project' do - should have_body_text /#{project.name}/ + is_expected.to have_body_text /#{project.name}/ end it 'contains new user role' do - should have_body_text /#{project_member.human_access}/ + is_expected.to have_body_text /#{project_member.human_access}/ end end @@ -430,29 +488,55 @@ describe Notify do let(:note) { create(:note, project: project, author: note_author) } before :each do - Note.stub(:find).with(note.id).and_return(note) + allow(Note).to receive(:find).with(note.id).and_return(note) end shared_examples 'a note email' do it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(note_author.name) - sender.address.should eq(gitlab_sender) + 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 - should deliver_to recipient.email + is_expected.to deliver_to recipient.notification_email end it 'contains the message from the note' do - should have_body_text /#{note.note}/ + is_expected.to have_body_text /#{note.note}/ + end + end + + describe 'on a commit that contains an image' do + let(:commit) { project.repository.commit } + let(:note_with_image) do + create(:note, + project: project, + author: note_author, + note: "![test](#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/uploads/12345/test.jpg)") + end + + let(:png) {File.read("#{Rails.root}/spec/fixtures/dk.png")} + let(:png_encoded) { Base64::encode64(png) } + + before :each do + file_path = File.join(Rails.root, 'public', 'uploads', note_with_image.project.path_with_namespace, '12345/test.jpg') + allow(File).to receive(:file?).with(file_path).and_return(true) + allow(File).to receive(:read).with(file_path).and_return(png) + allow(Note).to receive(:find).with(note_with_image.id).and_return(note_with_image) + allow(note_with_image).to receive(:noteable).and_return(commit) + end + + subject { Notify.note_commit_email(recipient.id, note_with_image.id) } + it 'replaces attached images with inline images' do + is_expected.to have_body_text URI.encode(png_encoded) end end describe 'on a commit' do let(:commit) { project.repository.commit } - before(:each) { note.stub(:noteable).and_return(commit) } + before(:each) { allow(note).to receive(:noteable).and_return(commit) } subject { Notify.note_commit_email(recipient.id, note.id) } @@ -460,18 +544,18 @@ describe Notify do it_behaves_like 'an answer to an existing thread', 'commits' it 'has the correct subject' do - should have_subject /#{commit.title} \(#{commit.short_id}\)/ + is_expected.to have_subject /#{commit.title} \(#{commit.short_id}\)/ end it 'contains a link to the commit' do - should have_body_text commit.short_id + is_expected.to have_body_text commit.short_id end end describe 'on a merge request' do let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } - let(:note_on_merge_request_path) { project_merge_request_path(project, merge_request, anchor: "note_#{note.id}") } - before(:each) { note.stub(:noteable).and_return(merge_request) } + let(:note_on_merge_request_path) { namespace_project_merge_request_path(project.namespace, project, merge_request, anchor: "note_#{note.id}") } + before(:each) { allow(note).to receive(:noteable).and_return(merge_request) } subject { Notify.note_merge_request_email(recipient.id, note.id) } @@ -479,18 +563,18 @@ describe Notify do it_behaves_like 'an answer to an existing thread', 'merge_request' it 'has the correct subject' do - should have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ + is_expected.to have_subject /#{merge_request.title} \(##{merge_request.iid}\)/ end it 'contains a link to the merge request note' do - should have_body_text /#{note_on_merge_request_path}/ + is_expected.to have_body_text /#{note_on_merge_request_path}/ end end describe 'on an issue' do let(:issue) { create(:issue, project: project) } - let(:note_on_issue_path) { project_issue_path(project, issue, anchor: "note_#{note.id}") } - before(:each) { note.stub(:noteable).and_return(issue) } + let(:note_on_issue_path) { namespace_project_issue_path(project.namespace, project, issue, anchor: "note_#{note.id}") } + before(:each) { allow(note).to receive(:noteable).and_return(issue) } subject { Notify.note_issue_email(recipient.id, note.id) } @@ -498,11 +582,11 @@ describe Notify do it_behaves_like 'an answer to an existing thread', 'issue' it 'has the correct subject' do - should have_subject /#{issue.title} \(##{issue.iid}\)/ + is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/ end it 'contains a link to the issue note' do - should have_body_text /#{note_on_issue_path}/ + is_expected.to have_body_text /#{note_on_issue_path}/ end end end @@ -518,15 +602,15 @@ describe Notify do it_behaves_like 'an email sent from GitLab' it 'has the correct subject' do - should have_subject /Access to group was granted/ + is_expected.to have_subject /Access to group was granted/ end it 'contains name of project' do - should have_body_text /#{group.name}/ + is_expected.to have_body_text /#{group.name}/ end it 'contains new user role' do - should have_body_text /#{membership.human_access}/ + is_expected.to have_body_text /#{membership.human_access}/ end end @@ -544,15 +628,15 @@ describe Notify do it_behaves_like 'an email sent from GitLab' it 'is sent to the new user' do - should deliver_to 'new-email@mail.com' + is_expected.to deliver_to 'new-email@mail.com' end it 'has the correct subject' do - should have_subject "Confirmation instructions" + is_expected.to have_subject "Confirmation instructions" end it 'includes a link to the site' do - should have_body_text /#{example_site_path}/ + is_expected.to have_body_text /#{example_site_path}/ end end @@ -561,34 +645,87 @@ describe Notify do let(:user) { create(:user) } let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_image_commit.id, sample_commit.id) } let(:commits) { Commit.decorate(compare.commits) } - let(:diff_path) { project_compare_path(project, from: commits.first, to: commits.last) } + let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base), to: Commit.new(compare.head)) } + let(:send_from_committer_email) { false } - subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) } + subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare, false, send_from_committer_email) } it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(user.name) + expect(sender.address).to eq(gitlab_sender) end it 'is sent to recipient' do - should deliver_to 'devs@company.name' + is_expected.to deliver_to 'devs@company.name' end it 'has the correct subject' do - should have_subject /#{commits.length} new commits pushed to repository/ + is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/ end it 'includes commits list' do - should have_body_text /Change some files/ + is_expected.to have_body_text /Change some files/ end it 'includes diffs' do - should have_body_text /def archive_formats_regex/ + is_expected.to have_body_text /def archive_formats_regex/ end it 'contains a link to the diff' do - should have_body_text /#{diff_path}/ + is_expected.to have_body_text /#{diff_path}/ + end + + it 'doesn not contain the misleading footer' do + is_expected.not_to have_body_text /you are a member of/ + end + + context "when set to send from committer email if domain matches" do + + let(:send_from_committer_email) { true } + + before do + allow(Gitlab.config.gitlab).to receive(:host).and_return("gitlab.corp.company.com") + end + + context "when the committer email domain is within the GitLab domain" do + + before do + user.update_attribute(:email, "user@company.com") + user.confirm! + end + + it "is sent from the committer email" do + sender = subject.header[:from].addrs[0] + expect(sender.address).to eq(user.email) + end + end + + context "when the committer email domain is not completely within the GitLab domain" do + + before do + user.update_attribute(:email, "user@something.company.com") + user.confirm! + end + + it "is sent from the default email" do + sender = subject.header[:from].addrs[0] + expect(sender.address).to eq(gitlab_sender) + end + end + + context "when the committer email domain is outside the GitLab domain" do + + before do + user.update_attribute(:email, "user@mpany.com") + user.confirm! + end + + it "is sent from the default email" do + sender = subject.header[:from].addrs[0] + expect(sender.address).to eq(gitlab_sender) + end + end end end @@ -597,34 +734,34 @@ describe Notify do let(:user) { create(:user) } let(:compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) } let(:commits) { Commit.decorate(compare.commits) } - let(:diff_path) { project_commit_path(project, commits.first) } + let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) } subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) } it 'is sent as the author' do sender = subject.header[:from].addrs[0] - sender.display_name.should eq(user.name) - sender.address.should eq(gitlab_sender) + expect(sender.display_name).to eq(user.name) + expect(sender.address).to eq(gitlab_sender) end it 'is sent to recipient' do - should deliver_to 'devs@company.name' + is_expected.to deliver_to 'devs@company.name' end it 'has the correct subject' do - should have_subject /#{commits.first.title}/ + is_expected.to have_subject /#{commits.first.title}/ end it 'includes commits list' do - should have_body_text /Change some files/ + is_expected.to have_body_text /Change some files/ end it 'includes diffs' do - should have_body_text /def archive_formats_regex/ + is_expected.to have_body_text /def archive_formats_regex/ end it 'contains a link to the diff' do - should have_body_text /#{diff_path}/ + is_expected.to have_body_text /#{diff_path}/ end end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb new file mode 100644 index 00000000000..b4f0b2c201a --- /dev/null +++ b/spec/models/application_setting_spec.rb @@ -0,0 +1,24 @@ +# == Schema Information +# +# Table name: application_settings +# +# id :integer not null, primary key +# default_projects_limit :integer +# default_branch_protection :integer +# signup_enabled :boolean +# signin_enabled :boolean +# gravatar_enabled :boolean +# sign_in_text :text +# created_at :datetime +# updated_at :datetime +# home_page_url :string(255) +# default_branch_protection :integer default(2) +# twitter_sharing_enabled :boolean default(TRUE) +# restricted_visibility_levels :text +# + +require 'spec_helper' + +describe ApplicationSetting, models: true do + it { expect(ApplicationSetting.create_from_defaults).to be_valid } +end diff --git a/spec/models/asana_service_spec.rb b/spec/models/asana_service_spec.rb new file mode 100644 index 00000000000..13c8d54a2af --- /dev/null +++ b/spec/models/asana_service_spec.rb @@ -0,0 +1,65 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe AsanaService, models: true do + describe 'Associations' do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe 'Validations' do + context 'active' do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of :api_key } + end + end + + describe 'Execute' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @asana = AsanaService.new + @asana.stub( + project: project, + project_id: project.id, + service_hook: true, + api_key: 'verySecret', + restrict_to_branch: 'master' + ) + end + + it 'should call Asana service to created a story' do + expect(Asana::Task).to receive(:find).with('123456').once + + @asana.check_commit('related to #123456', 'pushed') + end + + it 'should call Asana service to created a story and close a task' do + expect(Asana::Task).to receive(:find).with('456789').twice + + @asana.check_commit('fix #456789', 'pushed') + end + end +end diff --git a/spec/models/assembla_service_spec.rb b/spec/models/assembla_service_spec.rb deleted file mode 100644 index 4300090eb13..00000000000 --- a/spec/models/assembla_service_spec.rb +++ /dev/null @@ -1,48 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe AssemblaService, models: true do - describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe "Execute" do - let(:user) { create(:user) } - let(:project) { create(:project) } - - before do - @assembla_service = AssemblaService.new - @assembla_service.stub( - project_id: project.id, - project: project, - service_hook: true, - token: 'verySecret', - subdomain: 'project_name' - ) - @sample_data = GitPushService.new.sample_data(project, user) - @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' - WebMock.stub_request(:post, @api_url) - end - - it "should call Assembla API" do - @assembla_service.execute(@sample_data) - WebMock.should have_requested(:post, @api_url).with( - body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ - ).once - end - end -end diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb index 0f31c407c90..8ab72151a69 100644 --- a/spec/models/broadcast_message_spec.rb +++ b/spec/models/broadcast_message_spec.rb @@ -18,22 +18,22 @@ require 'spec_helper' describe BroadcastMessage do subject { create(:broadcast_message) } - it { should be_valid } + it { is_expected.to be_valid } describe :current do it "should return last message if time match" do broadcast_message = create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow) - BroadcastMessage.current.should == broadcast_message + expect(BroadcastMessage.current).to eq(broadcast_message) end it "should return nil if time not come" do broadcast_message = create(:broadcast_message, starts_at: Time.now.tomorrow, ends_at: Time.now + 2.days) - BroadcastMessage.current.should be_nil + expect(BroadcastMessage.current).to be_nil end it "should return nil if time has passed" do broadcast_message = create(:broadcast_message, starts_at: Time.now - 2.days, ends_at: Time.now.yesterday) - BroadcastMessage.current.should be_nil + expect(BroadcastMessage.current).to be_nil end end end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 6f201adc4e8..8b3d88640da 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -6,22 +6,22 @@ describe Commit do describe '#title' do it "returns no_commit_message when safe_message is blank" do - commit.stub(:safe_message).and_return('') - commit.title.should == "--no commit message" + allow(commit).to receive(:safe_message).and_return('') + expect(commit.title).to eq("--no commit message") end it "truncates a message without a newline at 80 characters" do message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.' - commit.stub(:safe_message).and_return(message) - commit.title.should == "#{message[0..79]}…" + allow(commit).to receive(:safe_message).and_return(message) + expect(commit.title).to eq("#{message[0..79]}…") end it "truncates a message with a newline before 80 characters at the newline" do message = commit.safe_message.split(" ").first - commit.stub(:safe_message).and_return(message + "\n" + message) - commit.title.should == message + allow(commit).to receive(:safe_message).and_return(message + "\n" + message) + expect(commit.title).to eq(message) end it "does not truncates a message with a newline after 80 but less 100 characters" do @@ -30,25 +30,25 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis Vivamus egestas lacinia lacus, sed rutrum mauris. eos - commit.stub(:safe_message).and_return(message) - commit.title.should == message.split("\n").first + allow(commit).to receive(:safe_message).and_return(message) + expect(commit.title).to eq(message.split("\n").first) end end describe "delegation" do subject { commit } - it { should respond_to(:message) } - it { should respond_to(:authored_date) } - it { should respond_to(:committed_date) } - it { should respond_to(:committer_email) } - it { should respond_to(:author_email) } - it { should respond_to(:parents) } - it { should respond_to(:date) } - it { should respond_to(:diffs) } - it { should respond_to(:tree) } - it { should respond_to(:id) } - it { should respond_to(:to_patch) } + it { is_expected.to respond_to(:message) } + it { is_expected.to respond_to(:authored_date) } + it { is_expected.to respond_to(:committed_date) } + it { is_expected.to respond_to(:committer_email) } + it { is_expected.to respond_to(:author_email) } + it { is_expected.to respond_to(:parents) } + it { is_expected.to respond_to(:date) } + it { is_expected.to respond_to(:diffs) } + it { is_expected.to respond_to(:tree) } + it { is_expected.to respond_to(:id) } + it { is_expected.to respond_to(:to_patch) } end describe '#closes_issues' do @@ -57,25 +57,21 @@ eos let(:other_issue) { create :issue, project: other_project } it 'detects issues that this commit is marked as closing' do - stub_const('Gitlab::ClosingIssueExtractor::ISSUE_CLOSING_REGEX', - /Fixes #\d+/) commit.stub(safe_message: "Fixes ##{issue.iid}") - commit.closes_issues(project).should == [issue] + expect(commit.closes_issues(project)).to eq([issue]) end it 'does not detect issues from other projects' do ext_ref = "#{other_project.path_with_namespace}##{other_issue.iid}" - stub_const('Gitlab::ClosingIssueExtractor::ISSUE_CLOSING_REGEX', - /^([Cc]loses|[Ff]ixes)/) commit.stub(safe_message: "Fixes #{ext_ref}") - commit.closes_issues(project).should be_empty + expect(commit.closes_issues(project)).to be_empty end end it_behaves_like 'a mentionable' do let(:subject) { commit } let(:mauthor) { create :user, email: commit.author_email } - let(:backref_text) { "commit #{subject.sha[0..5]}" } + let(:backref_text) { "commit #{subject.id}" } let(:set_mentionable_text) { ->(txt){ subject.stub(safe_message: txt) } } # Include the subject in the repository stub. diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 9cbc8990676..557c71b4d2c 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -4,63 +4,63 @@ describe Issue, "Issuable" do let(:issue) { create(:issue) } describe "Associations" do - it { should belong_to(:project) } - it { should belong_to(:author) } - it { should belong_to(:assignee) } - it { should have_many(:notes).dependent(:destroy) } + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:author) } + it { is_expected.to belong_to(:assignee) } + it { is_expected.to have_many(:notes).dependent(:destroy) } end describe "Validation" do before { subject.stub(set_iid: false) } - it { should validate_presence_of(:project) } - it { should validate_presence_of(:iid) } - it { should validate_presence_of(:author) } - it { should validate_presence_of(:title) } - it { should ensure_length_of(:title).is_at_least(0).is_at_most(255) } + it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:iid) } + it { is_expected.to validate_presence_of(:author) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to ensure_length_of(:title).is_at_least(0).is_at_most(255) } end describe "Scope" do - it { described_class.should respond_to(:opened) } - it { described_class.should respond_to(:closed) } - it { described_class.should respond_to(:assigned) } + it { expect(described_class).to respond_to(:opened) } + it { expect(described_class).to respond_to(:closed) } + it { expect(described_class).to respond_to(:assigned) } end describe ".search" do let!(:searchable_issue) { create(:issue, title: "Searchable issue") } it "matches by title" do - described_class.search('able').should == [searchable_issue] + expect(described_class.search('able')).to eq([searchable_issue]) end end describe "#today?" do it "returns true when created today" do # Avoid timezone differences and just return exactly what we want - Date.stub(:today).and_return(issue.created_at.to_date) - issue.today?.should be_true + allow(Date).to receive(:today).and_return(issue.created_at.to_date) + expect(issue.today?).to be_truthy end it "returns false when not created today" do - Date.stub(:today).and_return(Date.yesterday) - issue.today?.should be_false + allow(Date).to receive(:today).and_return(Date.yesterday) + expect(issue.today?).to be_falsey end end describe "#new?" do it "returns true when created today and record hasn't been updated" do - issue.stub(:today?).and_return(true) - issue.new?.should be_true + allow(issue).to receive(:today?).and_return(true) + expect(issue.new?).to be_truthy end it "returns false when not created today" do - issue.stub(:today?).and_return(false) - issue.new?.should be_false + allow(issue).to receive(:today?).and_return(false) + expect(issue.new?).to be_falsey end it "returns false when record has been updated" do - issue.stub(:today?).and_return(true) + allow(issue).to receive(:today?).and_return(true) issue.touch - issue.new?.should be_false + expect(issue.new?).to be_falsey end end end diff --git a/spec/models/concerns/mentionable_spec.rb b/spec/models/concerns/mentionable_spec.rb new file mode 100644 index 00000000000..eadb941a3fa --- /dev/null +++ b/spec/models/concerns/mentionable_spec.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe Issue, "Mentionable" do + describe :mentioned_users do + let!(:user) { create(:user, username: 'stranger') } + let!(:user2) { create(:user, username: 'john') } + let!(:issue) { create(:issue, description: '@stranger mentioned') } + + subject { issue.mentioned_users } + + it { is_expected.to include(user) } + it { is_expected.not_to include(user2) } + end +end diff --git a/spec/models/deploy_key_spec.rb b/spec/models/deploy_key_spec.rb index adbbbac875f..b32be8d7a7c 100644 --- a/spec/models/deploy_key_spec.rb +++ b/spec/models/deploy_key_spec.rb @@ -19,7 +19,7 @@ describe DeployKey do let(:deploy_key) { create(:deploy_key, projects: [project]) } describe "Associations" do - it { should have_many(:deploy_keys_projects) } - it { should have_many(:projects) } + it { is_expected.to have_many(:deploy_keys_projects) } + it { is_expected.to have_many(:projects) } end end diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb index 3e0e25ee39a..f351aab9238 100644 --- a/spec/models/deploy_keys_project_spec.rb +++ b/spec/models/deploy_keys_project_spec.rb @@ -13,12 +13,45 @@ require 'spec_helper' describe DeployKeysProject do describe "Associations" do - it { should belong_to(:deploy_key) } - it { should belong_to(:project) } + it { is_expected.to belong_to(:deploy_key) } + it { is_expected.to belong_to(:project) } end describe "Validation" do - it { should validate_presence_of(:project_id) } - it { should validate_presence_of(:deploy_key_id) } + it { is_expected.to validate_presence_of(:project_id) } + it { is_expected.to validate_presence_of(:deploy_key_id) } + end + + describe "Destroying" do + let(:project) { create(:project) } + subject { create(:deploy_keys_project, project: project) } + let(:deploy_key) { subject.deploy_key } + + context "when the deploy key is only used by this project" do + it "destroys the deploy key" do + subject.destroy + + expect { + deploy_key.reload + }.to raise_error(ActiveRecord::RecordNotFound) + end + end + + context "when the deploy key is used by more than one project" do + + let!(:other_project) { create(:project) } + + before do + other_project.deploy_keys << deploy_key + end + + it "doesn't destroy the deploy key" do + subject.destroy + + expect { + deploy_key.reload + }.not_to raise_error(ActiveRecord::RecordNotFound) + end + end end end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 1fdd959da9d..0f32f162a10 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -18,16 +18,16 @@ require 'spec_helper' describe Event do describe "Associations" do - it { should belong_to(:project) } - it { should belong_to(:target) } + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:target) } end describe "Respond to" do - it { should respond_to(:author_name) } - it { should respond_to(:author_email) } - it { should respond_to(:issue_title) } - it { should respond_to(:merge_request_title) } - it { should respond_to(:commits) } + it { is_expected.to respond_to(:author_name) } + it { is_expected.to respond_to(:author_email) } + it { is_expected.to respond_to(:issue_title) } + it { is_expected.to respond_to(:merge_request_title) } + it { is_expected.to respond_to(:commits) } end describe "Push event" do @@ -36,7 +36,7 @@ describe Event do @user = project.owner data = { - before: "0000000000000000000000000000000000000000", + before: Gitlab::Git::BLANK_SHA, after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e", ref: "refs/heads/master", user_id: @user.id, @@ -58,11 +58,10 @@ describe Event do ) end - it { @event.push?.should be_true } - it { @event.proper?.should be_true } - it { @event.new_branch?.should be_true } - it { @event.tag?.should be_false } - it { @event.branch_name.should == "master" } - it { @event.author.should == @user } + it { expect(@event.push?).to be_truthy } + it { expect(@event.proper?).to be_truthy } + it { expect(@event.tag?).to be_falsey } + it { expect(@event.branch_name).to eq("master") } + it { expect(@event.author).to eq(@user) } end end diff --git a/spec/models/flowdock_service_spec.rb b/spec/models/flowdock_service_spec.rb deleted file mode 100644 index 5540f0fa988..00000000000 --- a/spec/models/flowdock_service_spec.rb +++ /dev/null @@ -1,47 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe FlowdockService do - describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe "Execute" do - let(:user) { create(:user) } - let(:project) { create(:project) } - - before do - @flowdock_service = FlowdockService.new - @flowdock_service.stub( - project_id: project.id, - project: project, - service_hook: true, - token: 'verySecret' - ) - @sample_data = GitPushService.new.sample_data(project, user) - @api_url = 'https://api.flowdock.com/v1/git/verySecret' - WebMock.stub_request(:post, @api_url) - end - - it "should call FlowDock API" do - @flowdock_service.execute(@sample_data) - WebMock.should have_requested(:post, @api_url).with( - body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ - ).once - end - end -end diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb index 1845c6103f5..7d0ad44a92c 100644 --- a/spec/models/forked_project_link_spec.rb +++ b/spec/models/forked_project_link_spec.rb @@ -21,11 +21,11 @@ describe ForkedProjectLink, "add link on fork" do end it "project_to should know it is forked" do - @project_to.forked?.should be_true + expect(@project_to.forked?).to be_truthy end it "project should know who it is forked from" do - @project_to.forked_from_project.should == project_from + expect(@project_to.forked_from_project).to eq(project_from) end end @@ -43,15 +43,15 @@ describe :forked_from_project do it "project_to should know it is forked" do - project_to.forked?.should be_true + expect(project_to.forked?).to be_truthy end it "project_from should not be forked" do - project_from.forked?.should be_false + expect(project_from.forked?).to be_falsey end it "project_to.destroy should destroy fork_link" do - forked_project_link.should_receive(:destroy) + expect(forked_project_link).to receive(:destroy) project_to.destroy end diff --git a/spec/models/gemnasium_service_spec.rb b/spec/models/gemnasium_service_spec.rb deleted file mode 100644 index 60ffa6f8b05..00000000000 --- a/spec/models/gemnasium_service_spec.rb +++ /dev/null @@ -1,43 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe GemnasiumService do - describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe "Execute" do - let(:user) { create(:user) } - let(:project) { create(:project) } - - before do - @gemnasium_service = GemnasiumService.new - @gemnasium_service.stub( - project_id: project.id, - project: project, - service_hook: true, - token: 'verySecret', - api_key: 'GemnasiumUserApiKey' - ) - @sample_data = GitPushService.new.sample_data(project, user) - end - it "should call Gemnasium service" do - Gemnasium::GitlabService.should_receive(:execute).with(an_instance_of(Hash)).once - @gemnasium_service.execute(@sample_data) - end - end -end diff --git a/spec/models/gitlab_ci_service_spec.rb b/spec/models/gitlab_ci_service_spec.rb deleted file mode 100644 index ebc377047be..00000000000 --- a/spec/models/gitlab_ci_service_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe GitlabCiService do - describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe "Mass assignment" do - end - - describe 'commits methods' do - before do - @service = GitlabCiService.new - @service.stub( - service_hook: true, - project_url: 'http://ci.gitlab.org/projects/2', - token: 'verySecret' - ) - end - - describe :commit_status_path do - it { @service.commit_status_path("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c/status.json?token=verySecret"} - end - - describe :build_page do - it { @service.build_page("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c"} - end - end -end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 1d4ba8a2b85..9428224a64f 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -19,29 +19,29 @@ describe Group do let!(:group) { create(:group) } describe "Associations" do - it { should have_many :projects } - it { should have_many :group_members } + it { is_expected.to have_many :projects } + it { is_expected.to have_many :group_members } end - it { should validate_presence_of :name } - it { should validate_uniqueness_of(:name) } - it { should validate_presence_of :path } - it { should validate_uniqueness_of(:path) } - it { should_not validate_presence_of :owner } + it { is_expected.to validate_presence_of :name } + it { is_expected.to validate_uniqueness_of(:name) } + it { is_expected.to validate_presence_of :path } + it { is_expected.to validate_uniqueness_of(:path) } + it { is_expected.not_to validate_presence_of :owner } describe :users do - it { group.users.should == group.owners } + it { expect(group.users).to eq(group.owners) } end describe :human_name do - it { group.human_name.should == group.name } + it { expect(group.human_name).to eq(group.name) } end describe :add_users do let(:user) { create(:user) } before { group.add_user(user, GroupMember::MASTER) } - it { group.group_members.masters.map(&:user).should include(user) } + it { expect(group.group_members.masters.map(&:user)).to include(user) } end describe :add_users do @@ -49,10 +49,10 @@ describe Group do before { group.add_users([user.id], GroupMember::GUEST) } it "should update the group permission" do - group.group_members.guests.map(&:user).should include(user) + expect(group.group_members.guests.map(&:user)).to include(user) group.add_users([user.id], GroupMember::DEVELOPER) - group.group_members.developers.map(&:user).should include(user) - group.group_members.guests.map(&:user).should_not include(user) + expect(group.group_members.developers.map(&:user)).to include(user) + expect(group.group_members.guests.map(&:user)).not_to include(user) end end @@ -62,12 +62,12 @@ describe Group do it "should be true if avatar is image" do group.update_attribute(:avatar, 'uploads/avatar.png') - group.avatar_type.should be_true + expect(group.avatar_type).to be_truthy end it "should be false if avatar is html page" do group.update_attribute(:avatar, 'uploads/avatar.html') - group.avatar_type.should == ["only images allowed"] + expect(group.avatar_type).to eq(["only images allowed"]) end end end diff --git a/spec/models/project_hook_spec.rb b/spec/models/hooks/project_hook_spec.rb index 4e0d50d7f3f..4e0d50d7f3f 100644 --- a/spec/models/project_hook_spec.rb +++ b/spec/models/hooks/project_hook_spec.rb diff --git a/spec/models/service_hook_spec.rb b/spec/models/hooks/service_hook_spec.rb index 6ec82438dfe..96bf74d45da 100644 --- a/spec/models/service_hook_spec.rb +++ b/spec/models/hooks/service_hook_spec.rb @@ -19,6 +19,6 @@ require "spec_helper" describe ServiceHook do describe "Associations" do - it { should belong_to :service } + it { is_expected.to belong_to :service } end end diff --git a/spec/models/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index 4ab5261dc9d..810b311a40b 100644 --- a/spec/models/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -26,32 +26,32 @@ describe SystemHook do it "project_create hook" do Projects::CreateService.new(create(:user), name: 'empty').execute - WebMock.should have_requested(:post, @system_hook.url).with(body: /project_create/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /project_create/).once end it "project_destroy hook" do user = create(:user) project = create(:empty_project, namespace: user.namespace) Projects::DestroyService.new(project, user, {}).execute - WebMock.should have_requested(:post, @system_hook.url).with(body: /project_destroy/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /project_destroy/).once end it "user_create hook" do create(:user) - WebMock.should have_requested(:post, @system_hook.url).with(body: /user_create/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_create/).once end it "user_destroy hook" do user = create(:user) user.destroy - WebMock.should have_requested(:post, @system_hook.url).with(body: /user_destroy/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_destroy/).once end it "project_create hook" do user = create(:user) project = create(:project) project.team << [user, :master] - WebMock.should have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_add_to_team/).once end it "project_destroy hook" do @@ -59,7 +59,42 @@ describe SystemHook do project = create(:project) project.team << [user, :master] project.project_members.destroy_all - WebMock.should have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once + expect(WebMock).to have_requested(:post, @system_hook.url).with(body: /user_remove_from_team/).once end + + it 'group create hook' do + create(:group) + expect(WebMock).to have_requested(:post, @system_hook.url).with( + body: /group_create/ + ).once + end + + it 'group destroy hook' do + group = create(:group) + group.destroy + expect(WebMock).to have_requested(:post, @system_hook.url).with( + body: /group_destroy/ + ).once + end + + it 'group member create hook' do + group = create(:group) + user = create(:user) + group.add_user(user, Gitlab::Access::MASTER) + expect(WebMock).to have_requested(:post, @system_hook.url).with( + body: /user_add_to_group/ + ).once + end + + it 'group member destroy hook' do + group = create(:group) + user = create(:user) + group.add_user(user, Gitlab::Access::MASTER) + group.group_members.destroy_all + expect(WebMock).to have_requested(:post, @system_hook.url).with( + body: /user_remove_from_group/ + ).once + end + end end diff --git a/spec/models/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb index e9c04ee89cb..67ec9193ad7 100644 --- a/spec/models/web_hook_spec.rb +++ b/spec/models/hooks/web_hook_spec.rb @@ -19,25 +19,25 @@ require 'spec_helper' describe ProjectHook do describe "Associations" do - it { should belong_to :project } + it { is_expected.to belong_to :project } end describe "Mass assignment" do end describe "Validations" do - it { should validate_presence_of(:url) } + it { is_expected.to validate_presence_of(:url) } context "url format" do - it { should allow_value("http://example.com").for(:url) } - it { should allow_value("https://excample.com").for(:url) } - it { should allow_value("http://test.com/api").for(:url) } - it { should allow_value("http://test.com/api?key=abc").for(:url) } - it { should allow_value("http://test.com/api?key=abc&type=def").for(:url) } + it { is_expected.to allow_value("http://example.com").for(:url) } + it { is_expected.to allow_value("https://excample.com").for(:url) } + it { is_expected.to allow_value("http://test.com/api").for(:url) } + it { is_expected.to allow_value("http://test.com/api?key=abc").for(:url) } + it { is_expected.to allow_value("http://test.com/api?key=abc&type=def").for(:url) } - it { should_not allow_value("example.com").for(:url) } - it { should_not allow_value("ftp://example.com").for(:url) } - it { should_not allow_value("herp-and-derp").for(:url) } + it { is_expected.not_to allow_value("example.com").for(:url) } + it { is_expected.not_to allow_value("ftp://example.com").for(:url) } + it { is_expected.not_to allow_value("herp-and-derp").for(:url) } end end @@ -53,22 +53,22 @@ describe ProjectHook do it "POSTs to the web hook URL" do @project_hook.execute(@data) - WebMock.should have_requested(:post, @project_hook.url).once + expect(WebMock).to have_requested(:post, @project_hook.url).once end it "POSTs the data as JSON" do json = @data.to_json @project_hook.execute(@data) - WebMock.should have_requested(:post, @project_hook.url).with(body: json).once + expect(WebMock).to have_requested(:post, @project_hook.url).with(body: json).once end it "catches exceptions" do - WebHook.should_receive(:post).and_raise("Some HTTP Post error") + expect(WebHook).to receive(:post).and_raise("Some HTTP Post error") - lambda { + expect { @project_hook.execute(@data) - }.should raise_error + }.to raise_error end end end diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb index 6b6efe832e5..087e40c3d84 100644 --- a/spec/models/issue_spec.rb +++ b/spec/models/issue_spec.rb @@ -21,14 +21,14 @@ require 'spec_helper' describe Issue do describe "Associations" do - it { should belong_to(:milestone) } + it { is_expected.to belong_to(:milestone) } end describe "Mass assignment" do end describe 'modules' do - it { should include_module(Issuable) } + it { is_expected.to include_module(Issuable) } end subject { create(:issue) } @@ -36,10 +36,10 @@ describe Issue do describe '#is_being_reassigned?' do it 'returns true if the issue assignee has changed' do subject.assignee = create(:user) - subject.is_being_reassigned?.should be_true + expect(subject.is_being_reassigned?).to be_truthy end it 'returns false if the issue assignee has not changed' do - subject.is_being_reassigned?.should be_false + expect(subject.is_being_reassigned?).to be_falsey end end @@ -51,7 +51,7 @@ describe Issue do issue = create :issue, assignee: user end - Issue.open_for(user).count.should eq 2 + expect(Issue.open_for(user).count).to eq 2 end end diff --git a/spec/models/key_spec.rb b/spec/models/key_spec.rb index 95c0aed0ffe..a212b95a7d6 100644 --- a/spec/models/key_spec.rb +++ b/spec/models/key_spec.rb @@ -16,67 +16,67 @@ require 'spec_helper' describe Key do describe "Associations" do - it { should belong_to(:user) } + it { is_expected.to belong_to(:user) } end describe "Mass assignment" do end describe "Validation" do - it { should validate_presence_of(:title) } - it { should validate_presence_of(:key) } - it { should ensure_length_of(:title).is_within(0..255) } - it { should ensure_length_of(:key).is_within(0..5000) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_presence_of(:key) } + it { is_expected.to ensure_length_of(:title).is_within(0..255) } + it { is_expected.to ensure_length_of(:key).is_within(0..5000) } end describe "Methods" do - it { should respond_to :projects } + it { is_expected.to respond_to :projects } end context "validation of uniqueness" do let(:user) { create(:user) } it "accepts the key once" do - build(:key, user: user).should be_valid + expect(build(:key, user: user)).to be_valid end it "does not accept the exact same key twice" do create(:key, user: user) - build(:key, user: user).should_not be_valid + expect(build(:key, user: user)).not_to be_valid end it "does not accept a duplicate key with a different comment" do create(:key, user: user) duplicate = build(:key, user: user) duplicate.key << ' extra comment' - duplicate.should_not be_valid + expect(duplicate).not_to be_valid end end context "validate it is a fingerprintable key" do it "accepts the fingerprintable key" do - build(:key).should be_valid + expect(build(:key)).to be_valid end it "rejects the unfingerprintable key (contains space in middle)" do - build(:key_with_a_space_in_the_middle).should_not be_valid + expect(build(:key_with_a_space_in_the_middle)).not_to be_valid end it "rejects the unfingerprintable key (not a key)" do - build(:invalid_key).should_not be_valid + expect(build(:invalid_key)).not_to be_valid end end context 'callbacks' do it 'should add new key to authorized_file' do @key = build(:personal_key, id: 7) - GitlabShellWorker.should_receive(:perform_async).with(:add_key, @key.shell_id, @key.key) + expect(GitlabShellWorker).to receive(:perform_async).with(:add_key, @key.shell_id, @key.key) @key.save end it 'should remove key from authorized_file' do @key = create(:personal_key) - GitlabShellWorker.should_receive(:perform_async).with(:remove_key, @key.shell_id, @key.key) + expect(GitlabShellWorker).to receive(:perform_async).with(:remove_key, @key.shell_id, @key.key) @key.destroy end end diff --git a/spec/models/label_link_spec.rb b/spec/models/label_link_spec.rb index 0db60432ad3..8c240826582 100644 --- a/spec/models/label_link_spec.rb +++ b/spec/models/label_link_spec.rb @@ -14,8 +14,8 @@ require 'spec_helper' describe LabelLink do let(:label) { create(:label_link) } - it { label.should be_valid } + it { expect(label).to be_valid } - it { should belong_to(:label) } - it { should belong_to(:target) } + it { is_expected.to belong_to(:label) } + it { is_expected.to belong_to(:target) } end diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb index 31634648f04..8644ac46605 100644 --- a/spec/models/label_spec.rb +++ b/spec/models/label_spec.rb @@ -14,30 +14,30 @@ require 'spec_helper' describe Label do let(:label) { create(:label) } - it { label.should be_valid } + it { expect(label).to be_valid } - it { should belong_to(:project) } + it { is_expected.to belong_to(:project) } describe 'Validation' do it 'should validate color code' do - build(:label, color: 'G-ITLAB').should_not be_valid - build(:label, color: 'AABBCC').should_not be_valid - build(:label, color: '#AABBCCEE').should_not be_valid - build(:label, color: '#GGHHII').should_not be_valid - build(:label, color: '#').should_not be_valid - build(:label, color: '').should_not be_valid + expect(build(:label, color: 'G-ITLAB')).not_to be_valid + expect(build(:label, color: 'AABBCC')).not_to be_valid + expect(build(:label, color: '#AABBCCEE')).not_to be_valid + expect(build(:label, color: '#GGHHII')).not_to be_valid + expect(build(:label, color: '#')).not_to be_valid + expect(build(:label, color: '')).not_to be_valid - build(:label, color: '#AABBCC').should be_valid + expect(build(:label, color: '#AABBCC')).to be_valid end it 'should validate title' do - build(:label, title: 'G,ITLAB').should_not be_valid - build(:label, title: 'G?ITLAB').should_not be_valid - build(:label, title: 'G&ITLAB').should_not be_valid - build(:label, title: '').should_not be_valid + expect(build(:label, title: 'G,ITLAB')).not_to be_valid + expect(build(:label, title: 'G?ITLAB')).not_to be_valid + expect(build(:label, title: 'G&ITLAB')).not_to be_valid + expect(build(:label, title: '')).not_to be_valid - build(:label, title: 'GITLAB').should be_valid - build(:label, title: 'gitlab').should be_valid + expect(build(:label, title: 'GITLAB')).to be_valid + expect(build(:label, title: 'gitlab')).to be_valid end end end diff --git a/spec/models/group_member_spec.rb b/spec/models/members/group_member_spec.rb index 38657de6793..e206c11f33a 100644 --- a/spec/models/group_member_spec.rb +++ b/spec/models/members/group_member_spec.rb @@ -21,25 +21,25 @@ describe GroupMember do it "should send email to user" do membership = build(:group_member) membership.stub(notification_service: double('NotificationService').as_null_object) - membership.should_receive(:notification_service) + expect(membership).to receive(:notification_service) membership.save end end describe "#after_update" do before do - @membership = create :group_member - @membership.stub(notification_service: double('NotificationService').as_null_object) + @group_member = create :group_member + @group_member.stub(notification_service: double('NotificationService').as_null_object) end it "should send email to user" do - @membership.should_receive(:notification_service) - @membership.update_attribute(:access_level, GroupMember::MASTER) + expect(@group_member).to receive(:notification_service) + @group_member.update_attribute(:access_level, GroupMember::MASTER) end it "does not send an email when the access level has not changed" do - @membership.should_not_receive(:notification_service) - @membership.update_attribute(:access_level, GroupMember::OWNER) + expect(@group_member).not_to receive(:notification_service) + @group_member.update_attribute(:access_level, GroupMember::OWNER) end end end diff --git a/spec/models/project_member_spec.rb b/spec/models/members/project_member_spec.rb index 9b5f89b6d7d..521721f3577 100644 --- a/spec/models/project_member_spec.rb +++ b/spec/models/members/project_member_spec.rb @@ -33,19 +33,19 @@ describe ProjectMember do @status = @project_2.team.import(@project_1) end - it { @status.should be_true } + it { expect(@status).to be_truthy } describe 'project 2 should get user 1 as developer. user_2 should not be changed' do - it { @project_2.users.should include(@user_1) } - it { @project_2.users.should include(@user_2) } + it { expect(@project_2.users).to include(@user_1) } + it { expect(@project_2.users).to include(@user_2) } - it { @abilities.allowed?(@user_1, :write_project, @project_2).should be_true } - it { @abilities.allowed?(@user_2, :read_project, @project_2).should be_true } + it { expect(@abilities.allowed?(@user_1, :write_project, @project_2)).to be_truthy } + it { expect(@abilities.allowed?(@user_2, :read_project, @project_2)).to be_truthy } end describe 'project 1 should not be changed' do - it { @project_1.users.should include(@user_1) } - it { @project_1.users.should_not include(@user_2) } + it { expect(@project_1.users).to include(@user_1) } + it { expect(@project_1.users).not_to include(@user_2) } end end @@ -64,12 +64,12 @@ describe ProjectMember do ) end - it { @project_1.users.should include(@user_1) } - it { @project_1.users.should include(@user_2) } + it { expect(@project_1.users).to include(@user_1) } + it { expect(@project_1.users).to include(@user_2) } - it { @project_2.users.should include(@user_1) } - it { @project_2.users.should include(@user_2) } + it { expect(@project_2.users).to include(@user_1) } + it { expect(@project_2.users).to include(@user_2) } end describe :truncate_teams do @@ -86,7 +86,7 @@ describe ProjectMember do ProjectMember.truncate_teams([@project_1.id, @project_2.id]) end - it { @project_1.users.should be_empty } - it { @project_2.users.should be_empty } + it { expect(@project_1.users).to be_empty } + it { expect(@project_2.users).to be_empty } end end diff --git a/spec/models/members_spec.rb b/spec/models/members_spec.rb index 6866c4794c2..dfd3f7feb6b 100644 --- a/spec/models/members_spec.rb +++ b/spec/models/members_spec.rb @@ -2,19 +2,19 @@ require 'spec_helper' describe Member do describe "Associations" do - it { should belong_to(:user) } + it { is_expected.to belong_to(:user) } end describe "Validation" do subject { Member.new(access_level: Member::GUEST) } - it { should validate_presence_of(:user) } - it { should validate_presence_of(:source) } - it { should ensure_inclusion_of(:access_level).in_array(Gitlab::Access.values) } + it { is_expected.to validate_presence_of(:user) } + it { is_expected.to validate_presence_of(:source) } + it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.values) } end describe "Delegate methods" do - it { should respond_to(:user_name) } - it { should respond_to(:user_email) } + it { is_expected.to respond_to(:user_name) } + it { is_expected.to respond_to(:user_email) } end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 7b0d261d72f..d40503d791c 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -18,41 +18,42 @@ # iid :integer # description :text # position :integer default(0) +# locked_at :datetime # require 'spec_helper' describe MergeRequest do describe "Validation" do - it { should validate_presence_of(:target_branch) } - it { should validate_presence_of(:source_branch) } + it { is_expected.to validate_presence_of(:target_branch) } + it { is_expected.to validate_presence_of(:source_branch) } end describe "Mass assignment" do end describe "Respond to" do - it { should respond_to(:unchecked?) } - it { should respond_to(:can_be_merged?) } - it { should respond_to(:cannot_be_merged?) } + it { is_expected.to respond_to(:unchecked?) } + it { is_expected.to respond_to(:can_be_merged?) } + it { is_expected.to respond_to(:cannot_be_merged?) } end describe 'modules' do - it { should include_module(Issuable) } + it { is_expected.to include_module(Issuable) } end describe "#mr_and_commit_notes" do let!(:merge_request) { create(:merge_request) } before do - merge_request.stub(:commits) { [merge_request.source_project.repository.commit] } + allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] } create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project) create(:note, noteable: merge_request, project: merge_request.project) end it "should include notes for commits" do - merge_request.commits.should_not be_empty - merge_request.mr_and_commit_notes.count.should == 2 + expect(merge_request.commits).not_to be_empty + expect(merge_request.mr_and_commit_notes.count).to eq(2) end end @@ -61,10 +62,10 @@ describe MergeRequest do describe '#is_being_reassigned?' do it 'returns true if the merge_request assignee has changed' do subject.assignee = create(:user) - subject.is_being_reassigned?.should be_true + expect(subject.is_being_reassigned?).to be_truthy end it 'returns false if the merge request assignee has not changed' do - subject.is_being_reassigned?.should be_false + expect(subject.is_being_reassigned?).to be_falsey end end @@ -73,11 +74,11 @@ describe MergeRequest do subject.source_project = create(:project, namespace: create(:group)) subject.target_project = create(:project, namespace: create(:group)) - subject.for_fork?.should be_true + expect(subject.for_fork?).to be_truthy end it 'returns false if is not for a fork' do - subject.for_fork?.should be_false + expect(subject.for_fork?).to be_falsey end end @@ -95,14 +96,14 @@ describe MergeRequest do it 'accesses the set of issues that will be closed on acceptance' do subject.project.stub(default_branch: subject.target_branch) - subject.closes_issues.should == [issue0, issue1].sort_by(&:id) + expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id)) end it 'only lists issues as to be closed if it targets the default branch' do subject.project.stub(default_branch: 'master') subject.target_branch = 'something-else' - subject.closes_issues.should be_empty + expect(subject.closes_issues).to be_empty end it 'detects issues mentioned in the description' do @@ -110,7 +111,7 @@ describe MergeRequest do subject.description = "Closes ##{issue2.iid}" subject.project.stub(default_branch: subject.target_branch) - subject.closes_issues.should include(issue2) + expect(subject.closes_issues).to include(issue2) end end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index a3071c3251a..45171e1bf64 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -17,8 +17,8 @@ require 'spec_helper' describe Milestone do describe "Associations" do - it { should belong_to(:project) } - it { should have_many(:issues) } + it { is_expected.to belong_to(:project) } + it { is_expected.to have_many(:issues) } end describe "Mass assignment" do @@ -26,8 +26,8 @@ describe Milestone do describe "Validation" do before { subject.stub(set_iid: false) } - it { should validate_presence_of(:title) } - it { should validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to validate_presence_of(:project) } end let(:milestone) { create(:milestone) } @@ -36,30 +36,30 @@ describe Milestone do describe "#percent_complete" do it "should not count open issues" do milestone.issues << issue - milestone.percent_complete.should == 0 + expect(milestone.percent_complete).to eq(0) end it "should count closed issues" do issue.close milestone.issues << issue - milestone.percent_complete.should == 100 + expect(milestone.percent_complete).to eq(100) end it "should recover from dividing by zero" do - milestone.issues.should_receive(:count).and_return(0) - milestone.percent_complete.should == 100 + expect(milestone.issues).to receive(:count).and_return(0) + expect(milestone.percent_complete).to eq(100) end end describe "#expires_at" do it "should be nil when due_date is unset" do milestone.update_attributes(due_date: nil) - milestone.expires_at.should be_nil + expect(milestone.expires_at).to be_nil end it "should not be nil when due_date is set" do milestone.update_attributes(due_date: Date.tomorrow) - milestone.expires_at.should be_present + expect(milestone.expires_at).to be_present end end @@ -69,7 +69,7 @@ describe Milestone do milestone.stub(due_date: Date.today.prev_year) end - it { milestone.expired?.should be_true } + it { expect(milestone.expired?).to be_truthy } end context "not expired" do @@ -77,7 +77,7 @@ describe Milestone do milestone.stub(due_date: Date.today.next_year) end - it { milestone.expired?.should be_false } + it { expect(milestone.expired?).to be_falsey } end end @@ -89,7 +89,7 @@ describe Milestone do ) end - it { milestone.percent_complete.should == 75 } + it { expect(milestone.percent_complete).to eq(75) } end describe :items_count do @@ -99,14 +99,14 @@ describe Milestone do milestone.merge_requests << create(:merge_request) end - it { milestone.closed_items_count.should == 1 } - it { milestone.open_items_count.should == 2 } - it { milestone.total_items_count.should == 3 } - it { milestone.is_empty?.should be_false } + it { expect(milestone.closed_items_count).to eq(1) } + it { expect(milestone.open_items_count).to eq(2) } + it { expect(milestone.total_items_count).to eq(3) } + it { expect(milestone.is_empty?).to be_falsey } end describe :can_be_closed? do - it { milestone.can_be_closed?.should be_true } + it { expect(milestone.can_be_closed?).to be_truthy } end describe :is_empty? do @@ -116,7 +116,7 @@ describe Milestone do end it 'Should return total count of issues and merge requests assigned to milestone' do - milestone.total_items_count.should eq 2 + expect(milestone.total_items_count).to eq 2 end end @@ -129,14 +129,14 @@ describe Milestone do end it 'should be true if milestone active and all nested issues closed' do - milestone.can_be_closed?.should be_true + expect(milestone.can_be_closed?).to be_truthy end it 'should be false if milestone active and not all nested issues closed' do issue.milestone = milestone issue.save - milestone.can_be_closed?.should be_false + expect(milestone.can_be_closed?).to be_falsey end end diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 3562ebed1ff..ed6845c82cc 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -18,29 +18,29 @@ require 'spec_helper' describe Namespace do let!(:namespace) { create(:namespace) } - it { should have_many :projects } - it { should validate_presence_of :name } - it { should validate_uniqueness_of(:name) } - it { should validate_presence_of :path } - it { should validate_uniqueness_of(:path) } - it { should validate_presence_of :owner } + it { is_expected.to have_many :projects } + it { is_expected.to validate_presence_of :name } + it { is_expected.to validate_uniqueness_of(:name) } + it { is_expected.to validate_presence_of :path } + it { is_expected.to validate_uniqueness_of(:path) } + it { is_expected.to validate_presence_of :owner } describe "Mass assignment" do end describe "Respond to" do - it { should respond_to(:human_name) } - it { should respond_to(:to_param) } + it { is_expected.to respond_to(:human_name) } + it { is_expected.to respond_to(:to_param) } end - it { Namespace.global_id.should == 'GLN' } + it { expect(Namespace.global_id).to eq('GLN') } describe :to_param do - it { namespace.to_param.should == namespace.path } + it { expect(namespace.to_param).to eq(namespace.path) } end describe :human_name do - it { namespace.human_name.should == namespace.owner_name } + it { expect(namespace.human_name).to eq(namespace.owner_name) } end describe :search do @@ -48,8 +48,8 @@ describe Namespace do @namespace = create :namespace end - it { Namespace.search(@namespace.path).should == [@namespace] } - it { Namespace.search('unknown').should == [] } + it { expect(Namespace.search(@namespace.path)).to eq([@namespace]) } + it { expect(Namespace.search('unknown')).to eq([]) } end describe :move_dir do @@ -66,13 +66,23 @@ describe Namespace do new_path = @namespace.path + "_new" @namespace.stub(path_was: @namespace.path) @namespace.stub(path: new_path) - @namespace.move_dir.should be_true + expect(@namespace.move_dir).to be_truthy end end describe :rm_dir do it "should remove dir" do - namespace.rm_dir.should be_true + expect(namespace.rm_dir).to be_truthy end end + + describe :find_by_path_or_name do + before do + @namespace = create(:namespace, name: 'WoW', path: 'woW') + end + + it { expect(Namespace.find_by_path_or_name('wow')).to eq(@namespace) } + it { expect(Namespace.find_by_path_or_name('WOW')).to eq(@namespace) } + it { expect(Namespace.find_by_path_or_name('unknown')).to eq(nil) } + end end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index eeecd714a28..17cb439c90e 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -21,17 +21,17 @@ require 'spec_helper' describe Note do describe "Associations" do - it { should belong_to(:project) } - it { should belong_to(:noteable) } - it { should belong_to(:author).class_name('User') } + it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:noteable) } + it { is_expected.to belong_to(:author).class_name('User') } end describe "Mass assignment" do end describe "Validation" do - it { should validate_presence_of(:note) } - it { should validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:note) } + it { is_expected.to validate_presence_of(:project) } end describe "Voting score" do @@ -39,44 +39,44 @@ describe Note do it "recognizes a neutral note" do note = create(:votable_note, note: "This is not a +1 note") - note.should_not be_upvote - note.should_not be_downvote + expect(note).not_to be_upvote + expect(note).not_to be_downvote end it "recognizes a neutral emoji note" do note = build(:votable_note, note: "I would :+1: this, but I don't want to") - note.should_not be_upvote - note.should_not be_downvote + expect(note).not_to be_upvote + expect(note).not_to be_downvote end it "recognizes a +1 note" do note = create(:votable_note, note: "+1 for this") - note.should be_upvote + expect(note).to be_upvote end it "recognizes a +1 emoji as a vote" do note = build(:votable_note, note: ":+1: for this") - note.should be_upvote + expect(note).to be_upvote end it "recognizes a thumbsup emoji as a vote" do note = build(:votable_note, note: ":thumbsup: for this") - note.should be_upvote + expect(note).to be_upvote end it "recognizes a -1 note" do note = create(:votable_note, note: "-1 for this") - note.should be_downvote + expect(note).to be_downvote end it "recognizes a -1 emoji as a vote" do note = build(:votable_note, note: ":-1: for this") - note.should be_downvote + expect(note).to be_downvote end it "recognizes a thumbsdown emoji as a vote" do note = build(:votable_note, note: ":thumbsdown: for this") - note.should be_downvote + expect(note).to be_downvote end end @@ -87,22 +87,22 @@ describe Note do let!(:commit) { note.noteable } it "should be accessible through #noteable" do - note.commit_id.should == commit.id - note.noteable.should be_a(Commit) - note.noteable.should == commit + expect(note.commit_id).to eq(commit.id) + expect(note.noteable).to be_a(Commit) + expect(note.noteable).to eq(commit) end it "should save a valid note" do - note.commit_id.should == commit.id + expect(note.commit_id).to eq(commit.id) note.noteable == commit end it "should be recognized by #for_commit?" do - note.should be_for_commit + expect(note).to be_for_commit end it "should not be votable" do - note.should_not be_votable + expect(note).not_to be_votable end end @@ -111,20 +111,20 @@ describe Note do let!(:commit) { note.noteable } it "should save a valid note" do - note.commit_id.should == commit.id - note.noteable.id.should == commit.id + expect(note.commit_id).to eq(commit.id) + expect(note.noteable.id).to eq(commit.id) end it "should be recognized by #for_diff_line?" do - note.should be_for_diff_line + expect(note).to be_for_diff_line end it "should be recognized by #for_commit_diff_line?" do - note.should be_for_commit_diff_line + expect(note).to be_for_commit_diff_line end it "should not be votable" do - note.should_not be_votable + expect(note).not_to be_votable end end @@ -132,7 +132,7 @@ describe Note do let!(:note) { create(:note_on_issue, note: "+1 from me") } it "should not be votable" do - note.should be_votable + expect(note).to be_votable end end @@ -140,7 +140,7 @@ describe Note do let!(:note) { create(:note_on_merge_request, note: "+1 from me") } it "should be votable" do - note.should be_votable + expect(note).to be_votable end end @@ -148,7 +148,7 @@ describe Note do let!(:note) { create(:note_on_merge_request_diff, note: "+1 from me") } it "should not be votable" do - note.should_not be_votable + expect(note).not_to be_votable end end @@ -161,20 +161,35 @@ describe Note do subject { Note.create_status_change_note(thing, project, author, status, nil) } it 'creates and saves a Note' do - should be_a Note - subject.id.should_not be_nil + is_expected.to be_a Note + expect(subject.id).not_to be_nil end - its(:noteable) { should == thing } - its(:project) { should == thing.project } - its(:author) { should == author } - its(:note) { should =~ /Status changed to #{status}/ } + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(thing) } + end + + describe '#project' do + subject { super().project } + it { is_expected.to eq(thing.project) } + end + + describe '#author' do + subject { super().author } + it { is_expected.to eq(author) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to match(/Status changed to #{status}/) } + end it 'appends a back-reference if a closing mentionable is supplied' do commit = double('commit', gfm_reference: 'commit 123456') n = Note.create_status_change_note(thing, project, author, status, commit) - n.note.should =~ /Status changed to #{status} by commit 123456/ + expect(n.note).to match(/Status changed to #{status} by commit 123456/) end end @@ -187,19 +202,41 @@ describe Note do subject { Note.create_assignee_change_note(thing, project, author, assignee) } context 'creates and saves a Note' do - it { should be_a Note } - its(:id) { should_not be_nil } + it { is_expected.to be_a Note } + + describe '#id' do + subject { super().id } + it { is_expected.not_to be_nil } + end + end + + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(thing) } + end + + describe '#project' do + subject { super().project } + it { is_expected.to eq(thing.project) } + end + + describe '#author' do + subject { super().author } + it { is_expected.to eq(author) } end - its(:noteable) { should == thing } - its(:project) { should == thing.project } - its(:author) { should == author } - its(:note) { should =~ /Reassigned to @#{assignee.username}/ } + describe '#note' do + subject { super().note } + it { is_expected.to match(/Reassigned to @#{assignee.username}/) } + end context 'assignee is removed' do let(:assignee) { nil } - its(:note) { should =~ /Assignee removed/ } + describe '#note' do + subject { super().note } + it { is_expected.to match(/Assignee removed/) } + end end end @@ -216,58 +253,144 @@ describe Note do context 'issue from a merge request' do subject { Note.create_cross_reference_note(issue, mergereq, author, project) } - it { should be_valid } - its(:noteable) { should == issue } - its(:project) { should == issue.project } - its(:author) { should == author } - its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" } + it { is_expected.to be_valid } + + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(issue) } + end + + describe '#project' do + subject { super().project } + it { is_expected.to eq(issue.project) } + end + + describe '#author' do + subject { super().author } + it { is_expected.to eq(author) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in merge request !#{mergereq.iid}_") } + end end context 'issue from a commit' do subject { Note.create_cross_reference_note(issue, commit, author, project) } - it { should be_valid } - its(:noteable) { should == issue } - its(:note) { should == "_mentioned in commit #{commit.sha[0..5]}_" } + it { is_expected.to be_valid } + + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(issue) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in commit #{commit.sha}_") } + end end context 'merge request from an issue' do subject { Note.create_cross_reference_note(mergereq, issue, author, project) } - it { should be_valid } - its(:noteable) { should == mergereq } - its(:project) { should == mergereq.project } - its(:note) { should == "_mentioned in issue ##{issue.iid}_" } + it { is_expected.to be_valid } + + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(mergereq) } + end + + describe '#project' do + subject { super().project } + it { is_expected.to eq(mergereq.project) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in issue ##{issue.iid}_") } + end end context 'commit from a merge request' do subject { Note.create_cross_reference_note(commit, mergereq, author, project) } - it { should be_valid } - its(:noteable) { should == commit } - its(:project) { should == project } - its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" } + it { is_expected.to be_valid } + + describe '#noteable' do + subject { super().noteable } + it { is_expected.to eq(commit) } + end + + describe '#project' do + subject { super().project } + it { is_expected.to eq(project) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in merge request !#{mergereq.iid}_") } + end + end + + context 'commit contained in a merge request' do + subject { Note.create_cross_reference_note(mergereq.commits.first, mergereq, author, project) } + + it { is_expected.to be_nil } end context 'commit from issue' do subject { Note.create_cross_reference_note(commit, issue, author, project) } - it { should be_valid } - its(:noteable_type) { should == "Commit" } - its(:noteable_id) { should be_nil } - its(:commit_id) { should == commit.id } - its(:note) { should == "_mentioned in issue ##{issue.iid}_" } + it { is_expected.to be_valid } + + describe '#noteable_type' do + subject { super().noteable_type } + it { is_expected.to eq("Commit") } + end + + describe '#noteable_id' do + subject { super().noteable_id } + it { is_expected.to be_nil } + end + + describe '#commit_id' do + subject { super().commit_id } + it { is_expected.to eq(commit.id) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in issue ##{issue.iid}_") } + end end context 'commit from commit' do let(:parent_commit) { commit.parents.first } subject { Note.create_cross_reference_note(commit, parent_commit, author, project) } - it { should be_valid } - its(:noteable_type) { should == "Commit" } - its(:noteable_id) { should be_nil } - its(:commit_id) { should == commit.id } - its(:note) { should == "_mentioned in commit #{parent_commit.id[0...6]}_" } + it { is_expected.to be_valid } + + describe '#noteable_type' do + subject { super().noteable_type } + it { is_expected.to eq("Commit") } + end + + describe '#noteable_id' do + subject { super().noteable_id } + it { is_expected.to be_nil } + end + + describe '#commit_id' do + subject { super().commit_id } + it { is_expected.to eq(commit.id) } + end + + describe '#note' do + subject { super().note } + it { is_expected.to eq("_mentioned in commit #{parent_commit.id}_") } + end end end @@ -283,11 +406,11 @@ describe Note do end it 'detects if a mentionable has already been mentioned' do - Note.cross_reference_exists?(issue, commit0).should be_true + expect(Note.cross_reference_exists?(issue, commit0)).to be_truthy end it 'detects if a mentionable has not already been mentioned' do - Note.cross_reference_exists?(issue, commit1).should be_false + expect(Note.cross_reference_exists?(issue, commit1)).to be_falsey end context 'commit on commit' do @@ -295,8 +418,8 @@ describe Note do Note.create_cross_reference_note(commit0, commit1, author, project) end - it { Note.cross_reference_exists?(commit0, commit1).should be_true } - it { Note.cross_reference_exists?(commit1, commit0).should be_false } + it { expect(Note.cross_reference_exists?(commit0, commit1)).to be_truthy } + it { expect(Note.cross_reference_exists?(commit1, commit0)).to be_falsey } end end @@ -309,22 +432,22 @@ describe Note do it 'should recognize user-supplied notes as non-system' do @note = create(:note_on_issue) - @note.should_not be_system + expect(@note).not_to be_system end it 'should identify status-change notes as system notes' do @note = Note.create_status_change_note(issue, project, author, 'closed', nil) - @note.should be_system + expect(@note).to be_system end it 'should identify cross-reference notes as system notes' do @note = Note.create_cross_reference_note(issue, other, author, project) - @note.should be_system + expect(@note).to be_system end it 'should identify assignee-change notes as system notes' do @note = Note.create_assignee_change_note(issue, project, author, assignee) - @note.should be_system + expect(@note).to be_system end end @@ -345,9 +468,9 @@ describe Note do @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST) end - it { @abilities.allowed?(@u1, :read_note, @p1).should be_false } - it { @abilities.allowed?(@u2, :read_note, @p1).should be_true } - it { @abilities.allowed?(@u3, :read_note, @p1).should be_false } + it { expect(@abilities.allowed?(@u1, :read_note, @p1)).to be_falsey } + it { expect(@abilities.allowed?(@u2, :read_note, @p1)).to be_truthy } + it { expect(@abilities.allowed?(@u3, :read_note, @p1)).to be_falsey } end describe :write do @@ -356,9 +479,9 @@ describe Note do @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER) end - it { @abilities.allowed?(@u1, :write_note, @p1).should be_false } - it { @abilities.allowed?(@u2, :write_note, @p1).should be_true } - it { @abilities.allowed?(@u3, :write_note, @p1).should be_false } + it { expect(@abilities.allowed?(@u1, :write_note, @p1)).to be_falsey } + it { expect(@abilities.allowed?(@u2, :write_note, @p1)).to be_truthy } + it { expect(@abilities.allowed?(@u3, :write_note, @p1)).to be_falsey } end describe :admin do @@ -368,9 +491,9 @@ describe Note do @p2.project_members.create(user: @u3, access_level: ProjectMember::MASTER) end - it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false } - it { @abilities.allowed?(@u2, :admin_note, @p1).should be_true } - it { @abilities.allowed?(@u3, :admin_note, @p1).should be_false } + it { expect(@abilities.allowed?(@u1, :admin_note, @p1)).to be_falsey } + it { expect(@abilities.allowed?(@u2, :admin_note, @p1)).to be_truthy } + it { expect(@abilities.allowed?(@u3, :admin_note, @p1)).to be_falsey } end end diff --git a/spec/models/project_security_spec.rb b/spec/models/project_security_spec.rb index 5c8d1e7438b..1ee19003543 100644 --- a/spec/models/project_security_spec.rb +++ b/spec/models/project_security_spec.rb @@ -23,7 +23,7 @@ describe Project do describe "Non member rules" do it "should deny for non-project users any actions" do admin_actions.each do |action| - @abilities.allowed?(@u1, action, @p1).should be_false + expect(@abilities.allowed?(@u1, action, @p1)).to be_falsey end end end @@ -35,7 +35,7 @@ describe Project do it "should allow for project user any guest actions" do guest_actions.each do |action| - @abilities.allowed?(@u2, action, @p1).should be_true + expect(@abilities.allowed?(@u2, action, @p1)).to be_truthy end end end @@ -47,7 +47,7 @@ describe Project do it "should allow for project user any report actions" do report_actions.each do |action| - @abilities.allowed?(@u2, action, @p1).should be_true + expect(@abilities.allowed?(@u2, action, @p1)).to be_truthy end end end @@ -60,13 +60,13 @@ describe Project do it "should deny for developer master-specific actions" do [dev_actions - report_actions].each do |action| - @abilities.allowed?(@u2, action, @p1).should be_false + expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey end end it "should allow for project user any dev actions" do dev_actions.each do |action| - @abilities.allowed?(@u3, action, @p1).should be_true + expect(@abilities.allowed?(@u3, action, @p1)).to be_truthy end end end @@ -79,13 +79,13 @@ describe Project do it "should deny for developer master-specific actions" do [master_actions - dev_actions].each do |action| - @abilities.allowed?(@u2, action, @p1).should be_false + expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey end end it "should allow for project user any master actions" do master_actions.each do |action| - @abilities.allowed?(@u3, action, @p1).should be_true + expect(@abilities.allowed?(@u3, action, @p1)).to be_truthy end end end @@ -98,13 +98,13 @@ describe Project do it "should deny for masters admin-specific actions" do [admin_actions - master_actions].each do |action| - @abilities.allowed?(@u2, action, @p1).should be_false + expect(@abilities.allowed?(@u2, action, @p1)).to be_falsey end end it "should allow for project owner any admin actions" do admin_actions.each do |action| - @abilities.allowed?(@u4, action, @p1).should be_true + expect(@abilities.allowed?(@u4, action, @p1)).to be_truthy end end end diff --git a/spec/models/project_services/assembla_service_spec.rb b/spec/models/project_services/assembla_service_spec.rb new file mode 100644 index 00000000000..91730da1eec --- /dev/null +++ b/spec/models/project_services/assembla_service_spec.rb @@ -0,0 +1,53 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe AssemblaService, models: true do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @assembla_service = AssemblaService.new + @assembla_service.stub( + project_id: project.id, + project: project, + service_hook: true, + token: 'verySecret', + subdomain: 'project_name' + ) + @sample_data = Gitlab::PushDataBuilder.build_sample(project, user) + @api_url = 'https://atlas.assembla.com/spaces/project_name/github_tool?secret_key=verySecret' + WebMock.stub_request(:post, @api_url) + end + + it "should call Assembla API" do + @assembla_service.execute(@sample_data) + expect(WebMock).to have_requested(:post, @api_url).with( + body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ + ).once + end + end +end diff --git a/spec/models/buildbox_service_spec.rb b/spec/models/project_services/buildbox_service_spec.rb index 1d9ca51be16..39d7df54cf0 100644 --- a/spec/models/buildbox_service_spec.rb +++ b/spec/models/project_services/buildbox_service_spec.rb @@ -2,22 +2,27 @@ # # Table name: services # -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) # require 'spec_helper' describe BuildboxService do describe 'Associations' do - it { should belong_to :project } - it { should have_one :service_hook } + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } end describe 'commits methods' do @@ -38,35 +43,39 @@ describe BuildboxService do describe :webhook_url do it 'returns the webhook url' do - @service.webhook_url.should == + expect(@service.webhook_url).to eq( 'https://webhook.buildbox.io/deliver/secret-sauce-webhook-token' + ) end end describe :commit_status_path do it 'returns the correct status page' do - @service.commit_status_path('2ab7834c').should == + expect(@service.commit_status_path('2ab7834c')).to eq( 'https://gitlab.buildbox.io/status/secret-sauce-status-token.json?commit=2ab7834c' + ) end end describe :build_page do it 'returns the correct build page' do - @service.build_page('2ab7834c').should == + expect(@service.build_page('2ab7834c')).to eq( 'https://buildbox.io/account-name/example-project/builds?commit=2ab7834c' + ) end end describe :builds_page do it 'returns the correct path to the builds page' do - @service.builds_path.should == + expect(@service.builds_path).to eq( 'https://buildbox.io/account-name/example-project/builds?branch=default-brancho' + ) end end describe :status_img_path do it 'returns the correct path to the status image' do - @service.status_img_path.should == 'https://badge.buildbox.io/secret-sauce-status-token.svg' + expect(@service.status_img_path).to eq('https://badge.buildbox.io/secret-sauce-status-token.svg') end end end diff --git a/spec/models/project_services/flowdock_service_spec.rb b/spec/models/project_services/flowdock_service_spec.rb new file mode 100644 index 00000000000..73f68301a34 --- /dev/null +++ b/spec/models/project_services/flowdock_service_spec.rb @@ -0,0 +1,52 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe FlowdockService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @flowdock_service = FlowdockService.new + @flowdock_service.stub( + project_id: project.id, + project: project, + service_hook: true, + token: 'verySecret' + ) + @sample_data = Gitlab::PushDataBuilder.build_sample(project, user) + @api_url = 'https://api.flowdock.com/v1/git/verySecret' + WebMock.stub_request(:post, @api_url) + end + + it "should call FlowDock API" do + @flowdock_service.execute(@sample_data) + expect(WebMock).to have_requested(:post, @api_url).with( + body: /#{@sample_data[:before]}.*#{@sample_data[:after]}.*#{project.path}/ + ).once + end + end +end diff --git a/spec/models/project_services/gemnasium_service_spec.rb b/spec/models/project_services/gemnasium_service_spec.rb new file mode 100644 index 00000000000..d44064bbe6a --- /dev/null +++ b/spec/models/project_services/gemnasium_service_spec.rb @@ -0,0 +1,48 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe GemnasiumService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @gemnasium_service = GemnasiumService.new + @gemnasium_service.stub( + project_id: project.id, + project: project, + service_hook: true, + token: 'verySecret', + api_key: 'GemnasiumUserApiKey' + ) + @sample_data = Gitlab::PushDataBuilder.build_sample(project, user) + end + it "should call Gemnasium service" do + expect(Gemnasium::GitlabService).to receive(:execute).with(an_instance_of(Hash)).once + @gemnasium_service.execute(@sample_data) + end + end +end diff --git a/spec/models/project_services/gitlab_ci_service_spec.rb b/spec/models/project_services/gitlab_ci_service_spec.rb new file mode 100644 index 00000000000..8bfb19e524b --- /dev/null +++ b/spec/models/project_services/gitlab_ci_service_spec.rb @@ -0,0 +1,49 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe GitlabCiService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Mass assignment" do + end + + describe 'commits methods' do + before do + @service = GitlabCiService.new + @service.stub( + service_hook: true, + project_url: 'http://ci.gitlab.org/projects/2', + token: 'verySecret' + ) + end + + describe :commit_status_path do + it { expect(@service.commit_status_path("2ab7834c")).to eq("http://ci.gitlab.org/projects/2/commits/2ab7834c/status.json?token=verySecret")} + end + + describe :build_page do + it { expect(@service.build_page("2ab7834c")).to eq("http://ci.gitlab.org/projects/2/commits/2ab7834c")} + end + end +end diff --git a/spec/models/project_services/gitlab_issue_tracker_service_spec.rb b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb new file mode 100644 index 00000000000..959044dc727 --- /dev/null +++ b/spec/models/project_services/gitlab_issue_tracker_service_spec.rb @@ -0,0 +1,65 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe GitlabIssueTrackerService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + + describe 'project and issue urls' do + let(:project) { create(:project) } + + context 'with absolute urls' do + before do + @service = project.create_gitlab_issue_tracker_service(active: true) + end + + after do + @service.destroy! + end + + it 'should give the correct path' do + expect(@service.project_url).to eq("/#{project.path_with_namespace}/issues") + expect(@service.new_issue_url).to eq("/#{project.path_with_namespace}/issues/new") + expect(@service.issue_url(432)).to eq("/#{project.path_with_namespace}/issues/432") + end + end + + context 'with enabled relative urls' do + before do + Settings.gitlab.stub(:relative_url_root).and_return("/gitlab/root") + @service = project.create_gitlab_issue_tracker_service(active: true) + end + + after do + @service.destroy! + end + + it 'should give the correct path' do + expect(@service.project_url).to eq("/gitlab/root/#{project.path_with_namespace}/issues") + expect(@service.new_issue_url).to eq("/gitlab/root/#{project.path_with_namespace}/issues/new") + expect(@service.issue_url(432)).to eq("/gitlab/root/#{project.path_with_namespace}/issues/432") + end + end + end +end diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb new file mode 100644 index 00000000000..8ab847e6432 --- /dev/null +++ b/spec/models/project_services/hipchat_service_spec.rb @@ -0,0 +1,217 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe HipchatService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Execute" do + let(:hipchat) { HipchatService.new } + let(:user) { create(:user, username: 'username') } + let(:project) { create(:project, name: 'project') } + let(:api_url) { 'https://hipchat.example.com/v2/room/123456/notification?auth_token=verySecret' } + let(:project_name) { project.name_with_namespace.gsub(/\s/, '') } + + before(:each) do + hipchat.stub( + project_id: project.id, + project: project, + room: 123456, + server: 'https://hipchat.example.com', + token: 'verySecret' + ) + WebMock.stub_request(:post, api_url) + end + + context 'push events' do + let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } + + it "should call Hipchat API for push events" do + hipchat.execute(push_sample_data) + + expect(WebMock).to have_requested(:post, api_url).once + end + + it "should create a push message" do + message = hipchat.send(:create_push_message, push_sample_data) + + obj_attr = push_sample_data[:object_attributes] + branch = push_sample_data[:ref].gsub('refs/heads/', '') + expect(message).to include("#{user.name} pushed to branch " \ + "<a href=\"#{project.web_url}/commits/#{branch}\">#{branch}</a> of " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>") + end + end + + context 'tag_push events' do + let(:push_sample_data) { Gitlab::PushDataBuilder.build(project, user, Gitlab::Git::BLANK_SHA, '1' * 40, 'refs/tags/test', []) } + + it "should call Hipchat API for tag push events" do + hipchat.execute(push_sample_data) + + expect(WebMock).to have_requested(:post, api_url).once + end + + it "should create a tag push message" do + message = hipchat.send(:create_push_message, push_sample_data) + + obj_attr = push_sample_data[:object_attributes] + expect(message).to eq("#{user.name} pushed new tag " \ + "<a href=\"#{project.web_url}/commits/test\">test</a> to " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>\n") + end + end + + context 'issue events' do + let(:issue) { create(:issue, title: 'Awesome issue', description: 'please fix') } + let(:issue_service) { Issues::CreateService.new(project, user) } + let(:issues_sample_data) { issue_service.hook_data(issue, 'open') } + + it "should call Hipchat API for issue events" do + hipchat.execute(issues_sample_data) + + expect(WebMock).to have_requested(:post, api_url).once + end + + it "should create an issue message" do + message = hipchat.send(:create_issue_message, issues_sample_data) + + obj_attr = issues_sample_data[:object_attributes] + expect(message).to eq("#{user.name} opened " \ + "<a href=\"#{obj_attr[:url]}\">issue ##{obj_attr["iid"]}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "<b>Awesome issue</b>" \ + "<pre>please fix</pre>") + end + end + + context 'merge request events' do + let(:merge_request) { create(:merge_request, description: 'please fix', title: 'Awesome merge request', target_project: project, source_project: project) } + let(:merge_service) { MergeRequests::CreateService.new(project, user) } + let(:merge_sample_data) { merge_service.hook_data(merge_request, 'open') } + + it "should call Hipchat API for merge requests events" do + hipchat.execute(merge_sample_data) + + expect(WebMock).to have_requested(:post, api_url).once + end + + it "should create a merge request message" do + message = hipchat.send(:create_merge_request_message, + merge_sample_data) + + obj_attr = merge_sample_data[:object_attributes] + expect(message).to eq("#{user.name} opened " \ + "<a href=\"#{obj_attr[:url]}\">merge request ##{obj_attr["iid"]}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "<b>Awesome merge request</b>" \ + "<pre>please fix</pre>") + end + end + + context "Note events" do + let(:user) { create(:user) } + let(:project) { create(:project, creator_id: user.id) } + let(:issue) { create(:issue, project: project) } + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:snippet) { create(:project_snippet, project: project) } + let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') } + let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") } + let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")} + let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") } + + it "should call Hipchat API for commit comment events" do + data = Gitlab::NoteDataBuilder.build(commit_note, user) + hipchat.execute(data) + + expect(WebMock).to have_requested(:post, api_url).once + + message = hipchat.send(:create_message, data) + + obj_attr = data[:object_attributes] + commit_id = Commit.truncate_sha(data[:commit][:id]) + title = hipchat.send(:format_title, data[:commit][:message]) + + expect(message).to eq("#{user.name} commented on " \ + "<a href=\"#{obj_attr[:url]}\">commit #{commit_id}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "#{title}" \ + "<pre>a comment on a commit</pre>") + end + + it "should call Hipchat API for merge request comment events" do + data = Gitlab::NoteDataBuilder.build(merge_request_note, user) + hipchat.execute(data) + + expect(WebMock).to have_requested(:post, api_url).once + + message = hipchat.send(:create_message, data) + + obj_attr = data[:object_attributes] + merge_id = data[:merge_request]['iid'] + title = data[:merge_request]['title'] + + expect(message).to eq("#{user.name} commented on " \ + "<a href=\"#{obj_attr[:url]}\">merge request ##{merge_id}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "<b>#{title}</b>" \ + "<pre>merge request note</pre>") + end + + it "should call Hipchat API for issue comment events" do + data = Gitlab::NoteDataBuilder.build(issue_note, user) + hipchat.execute(data) + + message = hipchat.send(:create_message, data) + + obj_attr = data[:object_attributes] + issue_id = data[:issue]['iid'] + title = data[:issue]['title'] + + expect(message).to eq("#{user.name} commented on " \ + "<a href=\"#{obj_attr[:url]}\">issue ##{issue_id}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "<b>#{title}</b>" \ + "<pre>issue note</pre>") + end + + it "should call Hipchat API for snippet comment events" do + data = Gitlab::NoteDataBuilder.build(snippet_note, user) + hipchat.execute(data) + + expect(WebMock).to have_requested(:post, api_url).once + + message = hipchat.send(:create_message, data) + + obj_attr = data[:object_attributes] + snippet_id = data[:snippet]['id'] + title = data[:snippet]['title'] + + expect(message).to eq("#{user.name} commented on " \ + "<a href=\"#{obj_attr[:url]}\">snippet ##{snippet_id}</a> in " \ + "<a href=\"#{project.web_url}\">#{project_name}</a>: " \ + "<b>#{title}</b>" \ + "<pre>snippet note</pre>") + end + end + end +end diff --git a/spec/models/project_services/irker_service_spec.rb b/spec/models/project_services/irker_service_spec.rb new file mode 100644 index 00000000000..d55399bc360 --- /dev/null +++ b/spec/models/project_services/irker_service_spec.rb @@ -0,0 +1,108 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' +require 'socket' +require 'json' + +describe IrkerService do + describe 'Associations' do + it { should belong_to :project } + it { should have_one :service_hook } + end + + describe 'Validations' do + before do + subject.active = true + subject.properties['recipients'] = _recipients + end + + context 'active' do + let(:_recipients) { nil } + it { should validate_presence_of :recipients } + end + + context 'too many recipients' do + let(:_recipients) { 'a b c d' } + it 'should add an error if there is too many recipients' do + subject.send :check_recipients_count + subject.errors.should_not be_blank + end + end + + context '3 recipients' do + let(:_recipients) { 'a b c' } + it 'should not add an error if there is 3 recipients' do + subject.send :check_recipients_count + subject.errors.should be_blank + end + end + end + + describe 'Execute' do + let(:irker) { IrkerService.new } + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } + + let(:recipients) { '#commits' } + let(:colorize_messages) { '1' } + + before do + irker.stub( + active: true, + project: project, + project_id: project.id, + service_hook: true, + properties: { + 'recipients' => recipients, + 'colorize_messages' => colorize_messages + } + ) + irker.settings = { + server_ip: 'localhost', + server_port: 6659, + max_channels: 3, + default_irc_uri: 'irc://chat.freenode.net/' + } + irker.valid? + @irker_server = TCPServer.new 'localhost', 6659 + end + + after do + @irker_server.close + end + + it 'should send valid JSON messages to an Irker listener' do + irker.execute(sample_data) + + conn = @irker_server.accept + conn.readlines.each do |line| + msg = JSON.load(line.chomp("\n")) + msg.keys.should match_array(['to', 'privmsg']) + if msg['to'].is_a?(String) + msg['to'].should == 'irc://chat.freenode.net/#commits' + else + msg['to'].should match_array(['irc://chat.freenode.net/#commits']) + end + end + conn.close + end + end +end diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb new file mode 100644 index 00000000000..355911e6377 --- /dev/null +++ b/spec/models/project_services/jira_service_spec.rb @@ -0,0 +1,102 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe JiraService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Validations" do + context "active" do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of :project_url } + it { is_expected.to validate_presence_of :issues_url } + it { is_expected.to validate_presence_of :new_issue_url } + end + end + + describe 'description and title' do + let(:project) { create(:project) } + + context 'when it is not set' do + before do + @service = project.create_jira_service(active: true) + end + + after do + @service.destroy! + end + + it 'should be initialized' do + expect(@service.title).to eq('JIRA') + expect(@service.description).to eq("Jira issue tracker") + end + end + + context 'when it is set' do + before do + properties = { 'title' => 'Jira One', 'description' => 'Jira One issue tracker' } + @service = project.create_jira_service(active: true, properties: properties) + end + + after do + @service.destroy! + end + + it "should be correct" do + expect(@service.title).to eq('Jira One') + expect(@service.description).to eq('Jira One issue tracker') + end + end + end + + describe 'project and issue urls' do + let(:project) { create(:project) } + + context 'when gitlab.yml was initialized' do + before do + settings = { "jira" => { + "title" => "Jira", + "project_url" => "http://jira.sample/projects/project_a", + "issues_url" => "http://jira.sample/issues/:id", + "new_issue_url" => "http://jira.sample/projects/project_a/issues/new" + } + } + allow(Gitlab.config).to receive(:issues_tracker).and_return(settings) + @service = project.create_jira_service(active: true) + end + + after do + @service.destroy! + end + + it 'should be prepopulated with the settings' do + expect(@service.properties[:project_url]).to eq('http://jira.sample/projects/project_a') + expect(@service.properties[:issues_url]).to eq("http://jira.sample/issues/:id") + expect(@service.properties[:new_issue_url]).to eq("http://jira.sample/projects/project_a/issues/new") + end + end + end +end diff --git a/spec/models/project_services/pushover_service_spec.rb b/spec/models/project_services/pushover_service_spec.rb new file mode 100644 index 00000000000..5a18fd09bfc --- /dev/null +++ b/spec/models/project_services/pushover_service_spec.rb @@ -0,0 +1,74 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe PushoverService do + describe 'Associations' do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe 'Validations' do + context 'active' do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of :api_key } + it { is_expected.to validate_presence_of :user_key } + it { is_expected.to validate_presence_of :priority } + end + end + + describe 'Execute' do + let(:pushover) { PushoverService.new } + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } + + let(:api_key) { 'verySecret' } + let(:user_key) { 'verySecret' } + let(:device) { 'myDevice' } + let(:priority) { 0 } + let(:sound) { 'bike' } + let(:api_url) { 'https://api.pushover.net/1/messages.json' } + + before do + pushover.stub( + project: project, + project_id: project.id, + service_hook: true, + api_key: api_key, + user_key: user_key, + device: device, + priority: priority, + sound: sound + ) + + WebMock.stub_request(:post, api_url) + end + + it 'should call Pushover API' do + pushover.execute(sample_data) + + expect(WebMock).to have_requested(:post, api_url).once + end + end +end diff --git a/spec/models/project_services/slack_service/issue_message_spec.rb b/spec/models/project_services/slack_service/issue_message_spec.rb new file mode 100644 index 00000000000..8bca1fef44c --- /dev/null +++ b/spec/models/project_services/slack_service/issue_message_spec.rb @@ -0,0 +1,56 @@ +require 'spec_helper' + +describe SlackService::IssueMessage do + subject { SlackService::IssueMessage.new(args) } + + let(:args) { + { + user: { + name: 'Test User', + username: 'Test User' + }, + project_name: 'project_name', + project_url: 'somewhere.com', + + object_attributes: { + title: 'Issue title', + id: 10, + iid: 100, + assignee_id: 1, + url: 'url', + action: 'open', + state: 'opened', + description: 'issue description' + } + } + } + + let(:color) { '#345' } + + context 'open' do + it 'returns a message regarding opening of issues' do + expect(subject.pretext).to eq( + 'Test User opened <url|issue #100> in <somewhere.com|project_name>: '\ + '*Issue title*') + expect(subject.attachments).to eq([ + { + text: "issue description", + color: color, + } + ]) + end + end + + context 'close' do + before do + args[:object_attributes][:action] = 'close' + args[:object_attributes][:state] = 'closed' + end + it 'returns a message regarding closing of issues' do + expect(subject.pretext). to eq( + 'Test User closed <url|issue #100> in <somewhere.com|project_name>: '\ + '*Issue title*') + expect(subject.attachments).to be_empty + end + end +end diff --git a/spec/models/project_services/slack_service/merge_message_spec.rb b/spec/models/project_services/slack_service/merge_message_spec.rb new file mode 100644 index 00000000000..aeb408aa766 --- /dev/null +++ b/spec/models/project_services/slack_service/merge_message_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe SlackService::MergeMessage do + subject { SlackService::MergeMessage.new(args) } + + let(:args) { + { + user: { + name: 'Test User', + username: 'Test User' + }, + project_name: 'project_name', + project_url: 'somewhere.com', + + object_attributes: { + title: "Issue title\nSecond line", + id: 10, + iid: 100, + assignee_id: 1, + url: 'url', + state: 'opened', + description: 'issue description', + source_branch: 'source_branch', + target_branch: 'target_branch', + } + } + } + + let(:color) { '#345' } + + context 'open' do + it 'returns a message regarding opening of merge requests' do + expect(subject.pretext).to eq( + 'Test User opened <somewhere.com/merge_requests/100|merge request #100> '\ + 'in <somewhere.com|project_name>: *Issue title*') + expect(subject.attachments).to be_empty + end + end + + context 'close' do + before do + args[:object_attributes][:state] = 'closed' + end + it 'returns a message regarding closing of merge requests' do + expect(subject.pretext).to eq( + 'Test User closed <somewhere.com/merge_requests/100|merge request #100> '\ + 'in <somewhere.com|project_name>: *Issue title*') + expect(subject.attachments).to be_empty + end + end +end diff --git a/spec/models/project_services/slack_service/note_message_spec.rb b/spec/models/project_services/slack_service/note_message_spec.rb new file mode 100644 index 00000000000..21fb575480b --- /dev/null +++ b/spec/models/project_services/slack_service/note_message_spec.rb @@ -0,0 +1,129 @@ +require 'spec_helper' + +describe SlackService::NoteMessage do + let(:color) { '#345' } + + before do + @args = { + user: { + name: 'Test User', + username: 'username', + avatar_url: 'http://fakeavatar' + }, + project_name: 'project_name', + project_url: 'somewhere.com', + repository: { + name: 'project_name', + url: 'somewhere.com', + }, + object_attributes: { + id: 10, + note: 'comment on a commit', + url: 'url', + noteable_type: 'Commit' + } + } + end + + context 'commit notes' do + before do + @args[:object_attributes][:note] = 'comment on a commit' + @args[:object_attributes][:noteable_type] = 'Commit' + @args[:commit] = { + id: '5f163b2b95e6f53cbd428f5f0b103702a52b9a23', + message: "Added a commit message\ndetails\n123\n" + } + end + + it 'returns a message regarding notes on commits' do + message = SlackService::NoteMessage.new(@args) + expect(message.pretext).to eq("Test User commented on " \ + "<url|commit 5f163b2b> in <somewhere.com|project_name>: " \ + "*Added a commit message*") + expected_attachments = [ + { + text: "comment on a commit", + color: color, + } + ] + expect(message.attachments).to eq(expected_attachments) + end + end + + context 'merge request notes' do + before do + @args[:object_attributes][:note] = 'comment on a merge request' + @args[:object_attributes][:noteable_type] = 'MergeRequest' + @args[:merge_request] = { + id: 1, + iid: 30, + title: "merge request title\ndetails\n" + } + end + it 'returns a message regarding notes on a merge request' do + message = SlackService::NoteMessage.new(@args) + expect(message.pretext).to eq("Test User commented on " \ + "<url|merge request #30> in <somewhere.com|project_name>: " \ + "*merge request title*") + expected_attachments = [ + { + text: "comment on a merge request", + color: color, + } + ] + expect(message.attachments).to eq(expected_attachments) + end + end + + context 'issue notes' do + before do + @args[:object_attributes][:note] = 'comment on an issue' + @args[:object_attributes][:noteable_type] = 'Issue' + @args[:issue] = { + id: 1, + iid: 20, + title: "issue title\ndetails\n" + } + end + + it 'returns a message regarding notes on an issue' do + message = SlackService::NoteMessage.new(@args) + expect(message.pretext).to eq( + "Test User commented on " \ + "<url|issue #20> in <somewhere.com|project_name>: " \ + "*issue title*") + expected_attachments = [ + { + text: "comment on an issue", + color: color, + } + ] + expect(message.attachments).to eq(expected_attachments) + end + end + + context 'project snippet notes' do + before do + @args[:object_attributes][:note] = 'comment on a snippet' + @args[:object_attributes][:noteable_type] = 'Snippet' + @args[:snippet] = { + id: 5, + title: "snippet title\ndetails\n" + } + end + + it 'returns a message regarding notes on a project snippet' do + message = SlackService::NoteMessage.new(@args) + expect(message.pretext).to eq("Test User commented on " \ + "<url|snippet #5> in <somewhere.com|project_name>: " \ + "*snippet title*") + expected_attachments = [ + { + text: "comment on a snippet", + color: color, + } + ] + expect(message.attachments).to eq(expected_attachments) + end + end +end diff --git a/spec/models/slack_message_spec.rb b/spec/models/project_services/slack_service/push_message_spec.rb index 1cd58534702..10963481a12 100644 --- a/spec/models/slack_message_spec.rb +++ b/spec/models/project_services/slack_service/push_message_spec.rb @@ -1,7 +1,7 @@ -require_relative '../../app/models/project_services/slack_message' +require 'spec_helper' -describe SlackMessage do - subject { SlackMessage.new(args) } +describe SlackService::PushMessage do + subject { SlackService::PushMessage.new(args) } let(:args) { { @@ -25,41 +25,64 @@ describe SlackMessage do end it 'returns a message regarding pushes' do - subject.pretext.should == - 'user_name pushed to branch <url/commits/master|master> of ' << + expect(subject.pretext).to eq( + 'user_name pushed to branch <url/commits/master|master> of '\ '<url|project_name> (<url/compare/before...after|Compare changes>)' - subject.attachments.should == [ + ) + expect(subject.attachments).to eq([ { - text: "<url1|abcdefghi>: message1 - author1\n" << - "<url2|123456789>: message2 - author2", + text: "<url1|abcdefgh>: message1 - author1\n"\ + "<url2|12345678>: message2 - author2", color: color, } - ] + ]) + end + end + + context 'tag push' do + let(:args) { + { + after: 'after', + before: Gitlab::Git::BLANK_SHA, + project_name: 'project_name', + ref: 'refs/tags/new_tag', + user_name: 'user_name', + project_url: 'url' + } + } + + it 'returns a message regarding pushes' do + expect(subject.pretext).to eq('user_name pushed new tag ' \ + '<url/commits/new_tag|new_tag> to ' \ + '<url|project_name>') + expect(subject.attachments).to be_empty end end context 'new branch' do before do - args[:before] = '000000' + args[:before] = Gitlab::Git::BLANK_SHA end it 'returns a message regarding a new branch' do - subject.pretext.should == - 'user_name pushed new branch <url/commits/master|master> to ' << + expect(subject.pretext).to eq( + 'user_name pushed new branch <url/commits/master|master> to '\ '<url|project_name>' - subject.attachments.should be_empty + ) + expect(subject.attachments).to be_empty end end context 'removed branch' do before do - args[:after] = '000000' + args[:after] = Gitlab::Git::BLANK_SHA end it 'returns a message regarding a removed branch' do - subject.pretext.should == + expect(subject.pretext).to eq( 'user_name removed branch master from <url|project_name>' - subject.attachments.should be_empty + ) + expect(subject.attachments).to be_empty end end end diff --git a/spec/models/project_services/slack_service_spec.rb b/spec/models/project_services/slack_service_spec.rb new file mode 100644 index 00000000000..c36506644b3 --- /dev/null +++ b/spec/models/project_services/slack_service_spec.rb @@ -0,0 +1,170 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) +# + +require 'spec_helper' + +describe SlackService do + describe "Associations" do + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } + end + + describe "Validations" do + context "active" do + before do + subject.active = true + end + + it { is_expected.to validate_presence_of :webhook } + end + end + + describe "Execute" do + let(:slack) { SlackService.new } + let(:user) { create(:user) } + let(:project) { create(:project) } + let(:push_sample_data) { Gitlab::PushDataBuilder.build_sample(project, user) } + let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } + let(:username) { 'slack_username' } + let(:channel) { 'slack_channel' } + + before do + slack.stub( + project: project, + project_id: project.id, + service_hook: true, + webhook: webhook_url + ) + + WebMock.stub_request(:post, webhook_url) + + opts = { + title: 'Awesome issue', + description: 'please fix' + } + + issue_service = Issues::CreateService.new(project, user, opts) + @issue = issue_service.execute + @issues_sample_data = issue_service.hook_data(@issue, 'open') + + opts = { + title: 'Awesome merge_request', + description: 'please fix', + source_branch: 'stable', + target_branch: 'master' + } + merge_service = MergeRequests::CreateService.new(project, + user, opts) + @merge_request = merge_service.execute + @merge_sample_data = merge_service.hook_data(@merge_request, + 'open') + end + + it "should call Slack API for push events" do + slack.execute(push_sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it "should call Slack API for issue events" do + slack.execute(@issues_sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it "should call Slack API for merge requests events" do + slack.execute(@merge_sample_data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it 'should use the username as an option for slack when configured' do + slack.stub(username: username) + expect(Slack::Notifier).to receive(:new). + with(webhook_url, username: username). + and_return( + double(:slack_service).as_null_object + ) + slack.execute(push_sample_data) + end + + it 'should use the channel as an option when it is configured' do + slack.stub(channel: channel) + expect(Slack::Notifier).to receive(:new). + with(webhook_url, channel: channel). + and_return( + double(:slack_service).as_null_object + ) + slack.execute(push_sample_data) + end + end + + describe "Note events" do + let(:slack) { SlackService.new } + let(:user) { create(:user) } + let(:project) { create(:project, creator_id: user.id) } + let(:issue) { create(:issue, project: project) } + let(:merge_request) { create(:merge_request, source_project: project, target_project: project) } + let(:snippet) { create(:project_snippet, project: project) } + let(:commit_note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') } + let(:merge_request_note) { create(:note_on_merge_request, noteable_id: merge_request.id, note: "merge request note") } + let(:issue_note) { create(:note_on_issue, noteable_id: issue.id, note: "issue note")} + let(:snippet_note) { create(:note_on_project_snippet, noteable_id: snippet.id, note: "snippet note") } + let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' } + + before do + slack.stub( + project: project, + project_id: project.id, + service_hook: true, + webhook: webhook_url + ) + + WebMock.stub_request(:post, webhook_url) + end + + it "should call Slack API for commit comment events" do + data = Gitlab::NoteDataBuilder.build(commit_note, user) + slack.execute(data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it "should call Slack API for merge request comment events" do + data = Gitlab::NoteDataBuilder.build(merge_request_note, user) + slack.execute(data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it "should call Slack API for issue comment events" do + data = Gitlab::NoteDataBuilder.build(issue_note, user) + slack.execute(data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + + it "should call Slack API for snippet comment events" do + data = Gitlab::NoteDataBuilder.build(snippet_note, user) + slack.execute(data) + + expect(WebMock).to have_requested(:post, webhook_url).once + end + end +end diff --git a/spec/models/project_snippet_spec.rb b/spec/models/project_snippet_spec.rb index a6e1d9eef50..3e8f106d27f 100644 --- a/spec/models/project_snippet_spec.rb +++ b/spec/models/project_snippet_spec.rb @@ -19,13 +19,13 @@ require 'spec_helper' describe ProjectSnippet do describe "Associations" do - it { should belong_to(:project) } + it { is_expected.to belong_to(:project) } end describe "Mass assignment" do end describe "Validation" do - it { should validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:project) } end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 48b58400a1e..879a63dd9f9 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -24,103 +24,107 @@ # import_status :string(255) # repository_size :float default(0.0) # star_count :integer default(0), not null +# import_type :string(255) +# import_source :string(255) +# avatar :string(255) # require 'spec_helper' describe Project do - describe "Associations" do - it { should belong_to(:group) } - it { should belong_to(:namespace) } - it { should belong_to(:creator).class_name('User') } - it { should have_many(:users) } - it { should have_many(:events).dependent(:destroy) } - it { should have_many(:merge_requests).dependent(:destroy) } - it { should have_many(:issues).dependent(:destroy) } - it { should have_many(:milestones).dependent(:destroy) } - it { should have_many(:project_members).dependent(:destroy) } - it { should have_many(:notes).dependent(:destroy) } - it { should have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) } - it { should have_many(:deploy_keys_projects).dependent(:destroy) } - it { should have_many(:deploy_keys) } - it { should have_many(:hooks).dependent(:destroy) } - it { should have_many(:protected_branches).dependent(:destroy) } - it { should have_one(:forked_project_link).dependent(:destroy) } - it { should have_one(:slack_service).dependent(:destroy) } - it { should have_one(:pushover_service).dependent(:destroy) } + describe 'Associations' do + it { is_expected.to belong_to(:group) } + it { is_expected.to belong_to(:namespace) } + it { is_expected.to belong_to(:creator).class_name('User') } + it { is_expected.to have_many(:users) } + it { is_expected.to have_many(:events).dependent(:destroy) } + it { is_expected.to have_many(:merge_requests).dependent(:destroy) } + it { is_expected.to have_many(:issues).dependent(:destroy) } + it { is_expected.to have_many(:milestones).dependent(:destroy) } + it { is_expected.to have_many(:project_members).dependent(:destroy) } + it { is_expected.to have_many(:notes).dependent(:destroy) } + it { is_expected.to have_many(:snippets).class_name('ProjectSnippet').dependent(:destroy) } + it { is_expected.to have_many(:deploy_keys_projects).dependent(:destroy) } + it { is_expected.to have_many(:deploy_keys) } + it { is_expected.to have_many(:hooks).dependent(:destroy) } + it { is_expected.to have_many(:protected_branches).dependent(:destroy) } + it { is_expected.to have_one(:forked_project_link).dependent(:destroy) } + it { is_expected.to have_one(:slack_service).dependent(:destroy) } + it { is_expected.to have_one(:pushover_service).dependent(:destroy) } + it { is_expected.to have_one(:asana_service).dependent(:destroy) } end - describe "Mass assignment" do + describe 'Mass assignment' do end - describe "Validation" do + describe 'Validation' do let!(:project) { create(:project) } - it { should validate_presence_of(:name) } - it { should validate_uniqueness_of(:name).scoped_to(:namespace_id) } - it { should ensure_length_of(:name).is_within(0..255) } + it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) } + it { is_expected.to ensure_length_of(:name).is_within(0..255) } - it { should validate_presence_of(:path) } - it { should validate_uniqueness_of(:path).scoped_to(:namespace_id) } - it { should ensure_length_of(:path).is_within(0..255) } - it { should ensure_length_of(:description).is_within(0..2000) } - it { should validate_presence_of(:creator) } - it { should ensure_length_of(:issues_tracker_id).is_within(0..255) } - it { should validate_presence_of(:namespace) } + it { is_expected.to validate_presence_of(:path) } + it { is_expected.to validate_uniqueness_of(:path).scoped_to(:namespace_id) } + it { is_expected.to ensure_length_of(:path).is_within(0..255) } + it { is_expected.to ensure_length_of(:description).is_within(0..2000) } + it { is_expected.to validate_presence_of(:creator) } + it { is_expected.to ensure_length_of(:issues_tracker_id).is_within(0..255) } + it { is_expected.to validate_presence_of(:namespace) } - it "should not allow new projects beyond user limits" do + it 'should not allow new projects beyond user limits' do project2 = build(:project) - project2.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object) - project2.should_not be_valid - project2.errors[:limit_reached].first.should match(/Your project limit is 0/) + allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object) + expect(project2).not_to be_valid + expect(project2.errors[:limit_reached].first).to match(/Your project limit is 0/) end end - describe "Respond to" do - it { should respond_to(:url_to_repo) } - it { should respond_to(:repo_exists?) } - it { should respond_to(:satellite) } - it { should respond_to(:update_merge_requests) } - it { should respond_to(:execute_hooks) } - it { should respond_to(:name_with_namespace) } - it { should respond_to(:owner) } - it { should respond_to(:path_with_namespace) } + describe 'Respond to' do + it { is_expected.to respond_to(:url_to_repo) } + it { is_expected.to respond_to(:repo_exists?) } + it { is_expected.to respond_to(:satellite) } + it { is_expected.to respond_to(:update_merge_requests) } + it { is_expected.to respond_to(:execute_hooks) } + it { is_expected.to respond_to(:name_with_namespace) } + it { is_expected.to respond_to(:owner) } + it { is_expected.to respond_to(:path_with_namespace) } end - it "should return valid url to repo" do - project = Project.new(path: "somewhere") - project.url_to_repo.should == Gitlab.config.gitlab_shell.ssh_path_prefix + "somewhere.git" + it 'should return valid url to repo' do + project = Project.new(path: 'somewhere') + expect(project.url_to_repo).to eq(Gitlab.config.gitlab_shell.ssh_path_prefix + 'somewhere.git') end - it "returns the full web URL for this repo" do - project = Project.new(path: "somewhere") - project.web_url.should == "#{Gitlab.config.gitlab.url}/somewhere" + it 'returns the full web URL for this repo' do + project = Project.new(path: 'somewhere') + expect(project.web_url).to eq("#{Gitlab.config.gitlab.url}/somewhere") end - it "returns the web URL without the protocol for this repo" do - project = Project.new(path: "somewhere") - project.web_url_without_protocol.should == "#{Gitlab.config.gitlab.url.split("://")[1]}/somewhere" + it 'returns the web URL without the protocol for this repo' do + project = Project.new(path: 'somewhere') + expect(project.web_url_without_protocol).to eq("#{Gitlab.config.gitlab.url.split('://')[1]}/somewhere") end - describe "last_activity methods" do + describe 'last_activity methods' do let(:project) { create(:project) } let(:last_event) { double(created_at: Time.now) } - describe "last_activity" do - it "should alias last_activity to last_event" do + describe 'last_activity' do + it 'should alias last_activity to last_event' do project.stub(last_event: last_event) - project.last_activity.should == last_event + expect(project.last_activity).to eq(last_event) end end describe 'last_activity_date' do it 'returns the creation date of the project\'s last event if present' do last_activity_event = create(:event, project: project) - project.last_activity_at.to_i.should == last_event.created_at.to_i + expect(project.last_activity_at.to_i).to eq(last_event.created_at.to_i) end it 'returns the project\'s last update date if it has no events' do - project.last_activity_date.should == project.updated_at + expect(project.last_activity_date).to eq(project.updated_at) end end end @@ -132,73 +136,16 @@ describe Project do let(:prev_commit_id) { merge_request.commits.last.id } let(:commit_id) { merge_request.commits.first.id } - it "should close merge request if last commit from source branch was pushed to target branch" do + it 'should close merge request if last commit from source branch was pushed to target branch' do project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.target_branch}", key.user) merge_request.reload - merge_request.merged?.should be_true + expect(merge_request.merged?).to be_truthy end - it "should update merge request commits with new one if pushed to source branch" do + it 'should update merge request commits with new one if pushed to source branch' do project.update_merge_requests(prev_commit_id, commit_id, "refs/heads/#{merge_request.source_branch}", key.user) merge_request.reload - merge_request.last_commit.id.should == commit_id - end - end - - describe 'comment merge requests with commits' do - before do - @user = create(:user) - group = create(:group) - group.add_owner(@user) - - @project = create(:project, namespace: group) - @fork_project = Projects::ForkService.new(@project, @user).execute - @merge_request = create(:merge_request, source_project: @project, - source_branch: 'master', - target_branch: 'feature', - target_project: @project) - @fork_merge_request = create(:merge_request, source_project: @fork_project, - source_branch: 'master', - target_branch: 'feature', - target_project: @project) - - @commits = @merge_request.commits - end - - context 'push to origin repo source branch' do - before do - @project.comment_mr_with_commits('master', @commits, @user) - end - - it { @merge_request.notes.should_not be_empty } - it { @fork_merge_request.notes.should be_empty } - end - - context 'push to origin repo target branch' do - before do - @project.comment_mr_with_commits('feature', @commits, @user) - end - - it { @merge_request.notes.should be_empty } - it { @fork_merge_request.notes.should be_empty } - end - - context 'push to fork repo source branch' do - before do - @fork_project.comment_mr_with_commits('master', @commits, @user) - end - - it { @merge_request.notes.should be_empty } - it { @fork_merge_request.notes.should_not be_empty } - end - - context 'push to fork repo target branch' do - before do - @fork_project.comment_mr_with_commits('feature', @commits, @user) - end - - it { @merge_request.notes.should be_empty } - it { @fork_merge_request.notes.should be_empty } + expect(merge_request.last_commit.id).to eq(commit_id) end end @@ -209,8 +156,8 @@ describe Project do @project = create(:project, name: 'gitlabhq', namespace: @group) end - it { Project.find_with_namespace('gitlab/gitlabhq').should == @project } - it { Project.find_with_namespace('gitlab-ci').should be_nil } + it { expect(Project.find_with_namespace('gitlab/gitlabhq')).to eq(@project) } + it { expect(Project.find_with_namespace('gitlab-ci')).to be_nil } end end @@ -221,15 +168,15 @@ describe Project do @project = create(:project, name: 'gitlabhq', namespace: @group) end - it { @project.to_param.should == "gitlab/gitlabhq" } + it { expect(@project.to_param).to eq('gitlabhq') } end end describe :repository do let(:project) { create(:project) } - it "should return valid repo" do - project.repository.should be_kind_of(Repository) + it 'should return valid repo' do + expect(project.repository).to be_kind_of(Repository) end end @@ -239,29 +186,29 @@ describe Project do let(:not_existed_issue) { create(:issue) } let(:ext_project) { create(:redmine_project) } - it "should be true or if used internal tracker and issue exists" do - project.issue_exists?(existed_issue.iid).should be_true + it 'should be true or if used internal tracker and issue exists' do + expect(project.issue_exists?(existed_issue.iid)).to be_truthy end - it "should be false or if used internal tracker and issue not exists" do - project.issue_exists?(not_existed_issue.iid).should be_false + it 'should be false or if used internal tracker and issue not exists' do + expect(project.issue_exists?(not_existed_issue.iid)).to be_falsey end - it "should always be true if used other tracker" do - ext_project.issue_exists?(rand(100)).should be_true + it 'should always be true if used other tracker' do + expect(ext_project.issue_exists?(rand(100))).to be_truthy end end - describe :used_default_issues_tracker? do + describe :default_issues_tracker? do let(:project) { create(:project) } let(:ext_project) { create(:redmine_project) } it "should be true if used internal tracker" do - project.used_default_issues_tracker?.should be_true + expect(project.default_issues_tracker?).to be_truthy end it "should be false if used other tracker" do - ext_project.used_default_issues_tracker?.should be_false + expect(ext_project.default_issues_tracker?).to be_falsey end end @@ -269,20 +216,20 @@ describe Project do let(:project) { create(:project) } let(:ext_project) { create(:redmine_project) } - it "should be true for projects with external issues tracker if issues enabled" do - ext_project.can_have_issues_tracker_id?.should be_true + it 'should be true for projects with external issues tracker if issues enabled' do + expect(ext_project.can_have_issues_tracker_id?).to be_truthy end - it "should be false for projects with internal issue tracker if issues enabled" do - project.can_have_issues_tracker_id?.should be_false + it 'should be false for projects with internal issue tracker if issues enabled' do + expect(project.can_have_issues_tracker_id?).to be_falsey end - it "should be always false if issues disabled" do + it 'should be always false if issues disabled' do project.issues_enabled = false ext_project.issues_enabled = false - project.can_have_issues_tracker_id?.should be_false - ext_project.can_have_issues_tracker_id?.should be_false + expect(project.can_have_issues_tracker_id?).to be_falsey + expect(ext_project.can_have_issues_tracker_id?).to be_falsey end end @@ -293,8 +240,8 @@ describe Project do project.protected_branches.create(name: 'master') end - it { project.open_branches.map(&:name).should include('feature') } - it { project.open_branches.map(&:name).should_not include('master') } + it { expect(project.open_branches.map(&:name)).to include('feature') } + it { expect(project.open_branches.map(&:name)).not_to include('master') } end describe '#star_count' do @@ -365,4 +312,49 @@ describe Project do expect(project.star_count).to eq(0) end end + + describe :avatar_type do + let(:project) { create(:project) } + + it 'should be true if avatar is image' do + project.update_attribute(:avatar, 'uploads/avatar.png') + expect(project.avatar_type).to be_truthy + end + + it 'should be false if avatar is html page' do + project.update_attribute(:avatar, 'uploads/avatar.html') + expect(project.avatar_type).to eq(['only images allowed']) + end + end + + describe :avatar_url do + subject { project.avatar_url } + + let(:project) { create(:project) } + + context 'When avatar file is uploaded' do + before do + project.update_columns(avatar: 'uploads/avatar.png') + allow(project.avatar).to receive(:present?) { true } + end + + let(:avatar_path) do + "/uploads/project/avatar/#{project.id}/uploads/avatar.png" + end + + it { should eq "http://localhost#{avatar_path}" } + end + + context 'When avatar file in git' do + before do + allow(project).to receive(:avatar_in_git) { true } + end + + let(:avatar_path) do + "/#{project.namespace.name}/#{project.path}/avatar" + end + + it { should eq "http://localhost#{avatar_path}" } + end + end end diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb index bbf50b654f4..19201cc15a7 100644 --- a/spec/models/project_team_spec.rb +++ b/spec/models/project_team_spec.rb @@ -16,19 +16,19 @@ describe ProjectTeam do end describe 'members collection' do - it { project.team.masters.should include(master) } - it { project.team.masters.should_not include(guest) } - it { project.team.masters.should_not include(reporter) } - it { project.team.masters.should_not include(nonmember) } + it { expect(project.team.masters).to include(master) } + it { expect(project.team.masters).not_to include(guest) } + it { expect(project.team.masters).not_to include(reporter) } + it { expect(project.team.masters).not_to include(nonmember) } end describe 'access methods' do - it { project.team.master?(master).should be_true } - it { project.team.master?(guest).should be_false } - it { project.team.master?(reporter).should be_false } - it { project.team.master?(nonmember).should be_false } - it { project.team.member?(nonmember).should be_false } - it { project.team.member?(guest).should be_true } + it { expect(project.team.master?(master)).to be_truthy } + it { expect(project.team.master?(guest)).to be_falsey } + it { expect(project.team.master?(reporter)).to be_falsey } + it { expect(project.team.master?(nonmember)).to be_falsey } + it { expect(project.team.member?(nonmember)).to be_falsey } + it { expect(project.team.member?(guest)).to be_truthy } end end @@ -49,21 +49,21 @@ describe ProjectTeam do end describe 'members collection' do - it { project.team.reporters.should include(reporter) } - it { project.team.masters.should include(master) } - it { project.team.masters.should include(guest) } - it { project.team.masters.should_not include(reporter) } - it { project.team.masters.should_not include(nonmember) } + it { expect(project.team.reporters).to include(reporter) } + it { expect(project.team.masters).to include(master) } + it { expect(project.team.masters).to include(guest) } + it { expect(project.team.masters).not_to include(reporter) } + it { expect(project.team.masters).not_to include(nonmember) } end describe 'access methods' do - it { project.team.reporter?(reporter).should be_true } - it { project.team.master?(master).should be_true } - it { project.team.master?(guest).should be_true } - it { project.team.master?(reporter).should be_false } - it { project.team.master?(nonmember).should be_false } - it { project.team.member?(nonmember).should be_false } - it { project.team.member?(guest).should be_true } + it { expect(project.team.reporter?(reporter)).to be_truthy } + it { expect(project.team.master?(master)).to be_truthy } + it { expect(project.team.master?(guest)).to be_truthy } + it { expect(project.team.master?(reporter)).to be_falsey } + it { expect(project.team.master?(nonmember)).to be_falsey } + it { expect(project.team.member?(nonmember)).to be_falsey } + it { expect(project.team.member?(guest)).to be_truthy } end end end diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb index e4ee2fc5b13..2acdb7dfddc 100644 --- a/spec/models/project_wiki_spec.rb +++ b/spec/models/project_wiki_spec.rb @@ -12,19 +12,19 @@ describe ProjectWiki do describe "#path_with_namespace" do it "returns the project path with namespace with the .wiki extension" do - subject.path_with_namespace.should == project.path_with_namespace + ".wiki" + expect(subject.path_with_namespace).to eq(project.path_with_namespace + ".wiki") end end describe "#url_to_repo" do it "returns the correct ssh url to the repo" do - subject.url_to_repo.should == gitlab_shell.url_to_repo(subject.path_with_namespace) + expect(subject.url_to_repo).to eq(gitlab_shell.url_to_repo(subject.path_with_namespace)) end end describe "#ssh_url_to_repo" do it "equals #url_to_repo" do - subject.ssh_url_to_repo.should == subject.url_to_repo + expect(subject.ssh_url_to_repo).to eq(subject.url_to_repo) end end @@ -32,21 +32,21 @@ describe ProjectWiki do it "provides the full http url to the repo" do gitlab_url = Gitlab.config.gitlab.url repo_http_url = "#{gitlab_url}/#{subject.path_with_namespace}.git" - subject.http_url_to_repo.should == repo_http_url + expect(subject.http_url_to_repo).to eq(repo_http_url) end end describe "#wiki" do it "contains a Gollum::Wiki instance" do - subject.wiki.should be_a Gollum::Wiki + expect(subject.wiki).to be_a Gollum::Wiki end it "creates a new wiki repo if one does not yet exist" do - project_wiki.create_page("index", "test content").should be_true + expect(project_wiki.create_page("index", "test content")).to be_truthy end it "raises CouldNotCreateWikiError if it can't create the wiki repository" do - project_wiki.stub(:init_repo).and_return(false) + allow(project_wiki).to receive(:init_repo).and_return(false) expect { project_wiki.send(:create_repo!) }.to raise_exception(ProjectWiki::CouldNotCreateWikiError) end end @@ -54,21 +54,27 @@ describe ProjectWiki do describe "#empty?" do context "when the wiki repository is empty" do before do - Gitlab::Shell.any_instance.stub(:add_repository) do + allow_any_instance_of(Gitlab::Shell).to receive(:add_repository) do create_temp_repo("#{Rails.root}/tmp/test-git-base-path/non-existant.wiki.git") end - project.stub(:path_with_namespace).and_return("non-existant") + allow(project).to receive(:path_with_namespace).and_return("non-existant") end - its(:empty?) { should be_true } + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_truthy } + end end context "when the wiki has pages" do before do - create_page("index", "This is an awesome new Gollum Wiki") + project_wiki.create_page("index", "This is an awesome new Gollum Wiki") end - its(:empty?) { should be_false } + describe '#empty?' do + subject { super().empty? } + it { is_expected.to be_falsey } + end end end @@ -83,11 +89,11 @@ describe ProjectWiki do end it "returns an array of WikiPage instances" do - @pages.first.should be_a WikiPage + expect(@pages.first).to be_a WikiPage end it "returns the correct number of pages" do - @pages.count.should == 1 + expect(@pages.count).to eq(1) end end @@ -102,55 +108,55 @@ describe ProjectWiki do it "returns the latest version of the page if it exists" do page = subject.find_page("index page") - page.title.should == "index page" + expect(page.title).to eq("index page") end it "returns nil if the page does not exist" do - subject.find_page("non-existant").should == nil + expect(subject.find_page("non-existant")).to eq(nil) end it "can find a page by slug" do page = subject.find_page("index-page") - page.title.should == "index page" + expect(page.title).to eq("index page") end it "returns a WikiPage instance" do page = subject.find_page("index page") - page.should be_a WikiPage + expect(page).to be_a WikiPage end end describe '#find_file' do before do file = Gollum::File.new(subject.wiki) - Gollum::Wiki.any_instance. - stub(:file).with('image.jpg', 'master', true). + allow_any_instance_of(Gollum::Wiki). + to receive(:file).with('image.jpg', 'master', true). and_return(file) - Gollum::File.any_instance. - stub(:mime_type). + allow_any_instance_of(Gollum::File). + to receive(:mime_type). and_return('image/jpeg') - Gollum::Wiki.any_instance. - stub(:file).with('non-existant', 'master', true). + allow_any_instance_of(Gollum::Wiki). + to receive(:file).with('non-existant', 'master', true). and_return(nil) end after do - Gollum::Wiki.any_instance.unstub(:file) - Gollum::File.any_instance.unstub(:mime_type) + allow_any_instance_of(Gollum::Wiki).to receive(:file).and_call_original + allow_any_instance_of(Gollum::File).to receive(:mime_type).and_call_original end it 'returns the latest version of the file if it exists' do file = subject.find_file('image.jpg') - file.mime_type.should == 'image/jpeg' + expect(file.mime_type).to eq('image/jpeg') end it 'returns nil if the page does not exist' do - subject.find_file('non-existant').should == nil + expect(subject.find_file('non-existant')).to eq(nil) end it 'returns a Gollum::File instance' do file = subject.find_file('image.jpg') - file.should be_a Gollum::File + expect(file).to be_a Gollum::File end end @@ -160,23 +166,23 @@ describe ProjectWiki do end it "creates a new wiki page" do - subject.create_page("test page", "this is content").should_not == false - subject.pages.count.should == 1 + expect(subject.create_page("test page", "this is content")).not_to eq(false) + expect(subject.pages.count).to eq(1) end it "returns false when a duplicate page exists" do subject.create_page("test page", "content") - subject.create_page("test page", "content").should == false + expect(subject.create_page("test page", "content")).to eq(false) end it "stores an error message when a duplicate page exists" do 2.times { subject.create_page("test page", "content") } - subject.error_message.should =~ /Duplicate page:/ + expect(subject.error_message).to match(/Duplicate page:/) end it "sets the correct commit message" do subject.create_page("test page", "some content", :markdown, "commit message") - subject.pages.first.page.version.message.should == "commit message" + expect(subject.pages.first.page.version.message).to eq("commit message") end end @@ -193,11 +199,11 @@ describe ProjectWiki do end it "updates the content of the page" do - @page.raw_data.should == "some other content" + expect(@page.raw_data).to eq("some other content") end it "sets the correct commit message" do - @page.version.message.should == "updated page" + expect(@page.version.message).to eq("updated page") end end @@ -209,7 +215,7 @@ describe ProjectWiki do it "deletes the page" do subject.delete_page(@page) - subject.pages.count.should == 0 + expect(subject.pages.count).to eq(0) end end diff --git a/spec/models/protected_branch_spec.rb b/spec/models/protected_branch_spec.rb index af48c2c6d9e..1e6937b536c 100644 --- a/spec/models/protected_branch_spec.rb +++ b/spec/models/protected_branch_spec.rb @@ -2,25 +2,26 @@ # # Table name: protected_branches # -# id :integer not null, primary key -# project_id :integer not null -# name :string(255) not null -# created_at :datetime -# updated_at :datetime +# id :integer not null, primary key +# project_id :integer not null +# name :string(255) not null +# created_at :datetime +# updated_at :datetime +# developers_can_push :boolean default(FALSE), not null # require 'spec_helper' describe ProtectedBranch do describe 'Associations' do - it { should belong_to(:project) } + it { is_expected.to belong_to(:project) } end describe "Mass assignment" do end describe 'Validation' do - it { should validate_presence_of(:project) } - it { should validate_presence_of(:name) } + it { is_expected.to validate_presence_of(:project) } + it { is_expected.to validate_presence_of(:name) } end end diff --git a/spec/models/pushover_service_spec.rb b/spec/models/pushover_service_spec.rb deleted file mode 100644 index 59db69d7572..00000000000 --- a/spec/models/pushover_service_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe PushoverService do - describe 'Associations' do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe 'Validations' do - context 'active' do - before do - subject.active = true - end - - it { should validate_presence_of :api_key } - it { should validate_presence_of :user_key } - it { should validate_presence_of :priority } - end - end - - describe 'Execute' do - let(:pushover) { PushoverService.new } - let(:user) { create(:user) } - let(:project) { create(:project) } - let(:sample_data) { GitPushService.new.sample_data(project, user) } - - let(:api_key) { 'verySecret' } - let(:user_key) { 'verySecret' } - let(:device) { 'myDevice' } - let(:priority) { 0 } - let(:sound) { 'bike' } - let(:api_url) { 'https://api.pushover.net/1/messages.json' } - - before do - pushover.stub( - project: project, - project_id: project.id, - service_hook: true, - api_key: api_key, - user_key: user_key, - device: device, - priority: priority, - sound: sound - ) - - WebMock.stub_request(:post, api_url) - end - - it 'should call Pushover API' do - pushover.execute(sample_data) - - WebMock.should have_requested(:post, api_url).once - end - end -end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 6c3e221f343..b3a38f6c5b9 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -8,14 +8,37 @@ describe Repository do describe :branch_names_contains do subject { repository.branch_names_contains(sample_commit.id) } - it { should include('master') } - it { should_not include('feature') } - it { should_not include('fix') } + it { is_expected.to include('master') } + it { is_expected.not_to include('feature') } + it { is_expected.not_to include('fix') } end describe :last_commit_for_path do subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id } - it { should eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') } + it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') } + end + + context :timestamps_by_user_log do + before do + Date.stub(:today).and_return(Date.new(2015, 03, 01)) + end + + describe 'single e-mail for user' do + let(:user) { create(:user, email: sample_commit.author_email) } + + subject { repository.timestamps_by_user_log(user) } + + it { is_expected.to eq(["2014-08-06", "2014-07-31", "2014-07-31"]) } + end + + describe 'multiple emails for user' do + let(:email_alias) { create(:email, email: another_sample_commit.author_email) } + let(:user) { create(:user, email: sample_commit.author_email, emails: [email_alias]) } + + subject { repository.timestamps_by_user_log(user) } + + it { is_expected.to eq(["2015-01-10", "2014-08-06", "2014-07-31", "2014-07-31"]) } + end end end diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index c96f2b20529..735652aea78 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -2,14 +2,19 @@ # # Table name: services # -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# template :boolean default(FALSE) +# push_events :boolean default(TRUE) +# issues_events :boolean default(TRUE) +# merge_requests_events :boolean default(TRUE) +# tag_push_events :boolean default(TRUE) # require 'spec_helper' @@ -17,8 +22,8 @@ require 'spec_helper' describe Service do describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } + it { is_expected.to belong_to :project } + it { is_expected.to have_one :service_hook } end describe "Mass assignment" do @@ -40,7 +45,7 @@ describe Service do end describe :can_test do - it { @testable.should == true } + it { expect(@testable).to eq(true) } end end @@ -55,7 +60,32 @@ describe Service do end describe :can_test do - it { @testable.should == true } + it { expect(@testable).to eq(true) } + end + end + end + + describe "Template" do + describe "for pushover service" do + let(:service_template) { + PushoverService.create(template: true, properties: {device: 'MyDevice', sound: 'mic', priority: 4, api_key: '123456789'}) + } + let(:project) { create(:project) } + + describe 'should be prefilled for projects pushover service' do + before do + service_template + project.build_missing_services + end + + it "should have all fields prefilled" do + service = project.pushover_service + expect(service.template).to eq(false) + expect(service.device).to eq('MyDevice') + expect(service.sound).to eq('mic') + expect(service.priority).to eq(4) + expect(service.api_key).to eq('123456789') + end end end end diff --git a/spec/models/slack_service_spec.rb b/spec/models/slack_service_spec.rb deleted file mode 100644 index 95df38d9400..00000000000 --- a/spec/models/slack_service_spec.rb +++ /dev/null @@ -1,81 +0,0 @@ -# == Schema Information -# -# Table name: services -# -# id :integer not null, primary key -# type :string(255) -# title :string(255) -# project_id :integer not null -# created_at :datetime -# updated_at :datetime -# active :boolean default(FALSE), not null -# properties :text -# - -require 'spec_helper' - -describe SlackService do - describe "Associations" do - it { should belong_to :project } - it { should have_one :service_hook } - end - - describe "Validations" do - context "active" do - before do - subject.active = true - end - - it { should validate_presence_of :webhook } - end - end - - describe "Execute" do - let(:slack) { SlackService.new } - let(:slack_service) { SlackService.new } - let(:user) { create(:user) } - let(:project) { create(:project) } - let(:sample_data) { GitPushService.new.sample_data(project, user) } - let(:webhook) { 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI' } - let(:new_webhook) { 'https://hooks.gitlabhq.slack.com/services/cdIj4r4LfXUOySDUjp0tk3OI' } - let(:api_url) { - 'https://gitlabhq.slack.com/services/hooks/incoming-webhook?token=cdIj4r4LfXUOySDUjp0tk3OI' - } - - before do - slack.stub( - project: project, - project_id: project.id, - service_hook: true, - webhook: webhook - ) - - WebMock.stub_request(:post, api_url) - end - - it "should call Slack API" do - slack.execute(sample_data) - - WebMock.should have_requested(:post, api_url).once - end - - context 'with new webhook syntax' do - before do - slack_service.stub( - project: project, - project_id: project.id, - service_hook: true, - webhook: new_webhook - ) - - WebMock.stub_request(:post, api_url) - end - - it "should call Slack API" do - slack_service.execute(sample_data) - - WebMock.should have_requested(:post, api_url).once - end - end - end -end diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb index 1ef2c512c1f..e37dcc75230 100644 --- a/spec/models/snippet_spec.rb +++ b/spec/models/snippet_spec.rb @@ -19,22 +19,22 @@ require 'spec_helper' describe Snippet do describe "Associations" do - it { should belong_to(:author).class_name('User') } - it { should have_many(:notes).dependent(:destroy) } + it { is_expected.to belong_to(:author).class_name('User') } + it { is_expected.to have_many(:notes).dependent(:destroy) } end describe "Mass assignment" do end describe "Validation" do - it { should validate_presence_of(:author) } + it { is_expected.to validate_presence_of(:author) } - it { should validate_presence_of(:title) } - it { should ensure_length_of(:title).is_within(0..255) } + it { is_expected.to validate_presence_of(:title) } + it { is_expected.to ensure_length_of(:title).is_within(0..255) } - it { should validate_presence_of(:file_name) } - it { should ensure_length_of(:title).is_within(0..255) } + it { is_expected.to validate_presence_of(:file_name) } + it { is_expected.to ensure_length_of(:title).is_within(0..255) } - it { should validate_presence_of(:content) } + it { is_expected.to validate_presence_of(:content) } end end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 0250014bc21..10e90cae143 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -2,79 +2,85 @@ # # Table name: users # -# id :integer not null, primary key -# email :string(255) default(""), not null -# encrypted_password :string(255) default(""), not null -# reset_password_token :string(255) -# reset_password_sent_at :datetime -# remember_created_at :datetime -# sign_in_count :integer default(0) -# current_sign_in_at :datetime -# last_sign_in_at :datetime -# current_sign_in_ip :string(255) -# last_sign_in_ip :string(255) -# created_at :datetime -# updated_at :datetime -# name :string(255) -# admin :boolean default(FALSE), not null -# projects_limit :integer default(10) -# skype :string(255) default(""), not null -# linkedin :string(255) default(""), not null -# twitter :string(255) default(""), not null -# authentication_token :string(255) -# theme_id :integer default(1), not null -# bio :string(255) -# failed_attempts :integer default(0) -# locked_at :datetime -# extern_uid :string(255) -# provider :string(255) -# username :string(255) -# can_create_group :boolean default(TRUE), not null -# can_create_team :boolean default(TRUE), not null -# state :string(255) -# color_scheme_id :integer default(1), not null -# notification_level :integer default(1), not null -# password_expires_at :datetime -# created_by_id :integer -# last_credential_check_at :datetime -# avatar :string(255) -# confirmation_token :string(255) -# confirmed_at :datetime -# confirmation_sent_at :datetime -# unconfirmed_email :string(255) -# hide_no_ssh_key :boolean default(FALSE) -# website_url :string(255) default(""), not null +# id :integer not null, primary key +# email :string(255) default(""), not null +# encrypted_password :string(255) default(""), not null +# reset_password_token :string(255) +# reset_password_sent_at :datetime +# remember_created_at :datetime +# sign_in_count :integer default(0) +# current_sign_in_at :datetime +# last_sign_in_at :datetime +# current_sign_in_ip :string(255) +# last_sign_in_ip :string(255) +# created_at :datetime +# updated_at :datetime +# name :string(255) +# admin :boolean default(FALSE), not null +# projects_limit :integer default(10) +# skype :string(255) default(""), not null +# linkedin :string(255) default(""), not null +# twitter :string(255) default(""), not null +# authentication_token :string(255) +# theme_id :integer default(1), not null +# bio :string(255) +# failed_attempts :integer default(0) +# locked_at :datetime +# username :string(255) +# can_create_group :boolean default(TRUE), not null +# can_create_team :boolean default(TRUE), not null +# state :string(255) +# color_scheme_id :integer default(1), not null +# notification_level :integer default(1), not null +# password_expires_at :datetime +# created_by_id :integer +# last_credential_check_at :datetime +# avatar :string(255) +# confirmation_token :string(255) +# confirmed_at :datetime +# confirmation_sent_at :datetime +# unconfirmed_email :string(255) +# hide_no_ssh_key :boolean default(FALSE) +# website_url :string(255) default(""), not null +# github_access_token :string(255) +# gitlab_access_token :string(255) +# notification_email :string(255) +# hide_no_password :boolean default(FALSE) +# password_automatically_set :boolean default(FALSE) +# bitbucket_access_token :string(255) +# bitbucket_access_token_secret :string(255) # require 'spec_helper' describe User do describe "Associations" do - it { should have_one(:namespace) } - it { should have_many(:snippets).class_name('Snippet').dependent(:destroy) } - it { should have_many(:project_members).dependent(:destroy) } - it { should have_many(:groups) } - it { should have_many(:keys).dependent(:destroy) } - it { should have_many(:events).class_name('Event').dependent(:destroy) } - it { should have_many(:recent_events).class_name('Event') } - it { should have_many(:issues).dependent(:destroy) } - it { should have_many(:notes).dependent(:destroy) } - it { should have_many(:assigned_issues).dependent(:destroy) } - it { should have_many(:merge_requests).dependent(:destroy) } - it { should have_many(:assigned_merge_requests).dependent(:destroy) } + it { is_expected.to have_one(:namespace) } + it { is_expected.to have_many(:snippets).class_name('Snippet').dependent(:destroy) } + it { is_expected.to have_many(:project_members).dependent(:destroy) } + it { is_expected.to have_many(:groups) } + it { is_expected.to have_many(:keys).dependent(:destroy) } + it { is_expected.to have_many(:events).class_name('Event').dependent(:destroy) } + it { is_expected.to have_many(:recent_events).class_name('Event') } + it { is_expected.to have_many(:issues).dependent(:destroy) } + it { is_expected.to have_many(:notes).dependent(:destroy) } + it { is_expected.to have_many(:assigned_issues).dependent(:destroy) } + it { is_expected.to have_many(:merge_requests).dependent(:destroy) } + it { is_expected.to have_many(:assigned_merge_requests).dependent(:destroy) } + it { is_expected.to have_many(:identities).dependent(:destroy) } end describe "Mass assignment" do end describe 'validations' do - it { should validate_presence_of(:username) } - it { should validate_presence_of(:projects_limit) } - it { should validate_numericality_of(:projects_limit) } - it { should allow_value(0).for(:projects_limit) } - it { should_not allow_value(-1).for(:projects_limit) } + it { is_expected.to validate_presence_of(:username) } + it { is_expected.to validate_presence_of(:projects_limit) } + it { is_expected.to validate_numericality_of(:projects_limit) } + it { is_expected.to allow_value(0).for(:projects_limit) } + it { is_expected.not_to allow_value(-1).for(:projects_limit) } - it { should ensure_length_of(:bio).is_within(0..255) } + it { is_expected.to ensure_length_of(:bio).is_within(0..255) } describe 'email' do it 'accepts info@example.com' do @@ -110,34 +116,34 @@ describe User do end describe "Respond to" do - it { should respond_to(:is_admin?) } - it { should respond_to(:name) } - it { should respond_to(:private_token) } + it { is_expected.to respond_to(:is_admin?) } + it { is_expected.to respond_to(:name) } + it { is_expected.to respond_to(:private_token) } end describe '#generate_password' do it "should execute callback when force_random_password specified" do user = build(:user, force_random_password: true) - user.should_receive(:generate_password) + expect(user).to receive(:generate_password) user.save end it "should not generate password by default" do user = create(:user, password: 'abcdefghe') - user.password.should == 'abcdefghe' + expect(user.password).to eq('abcdefghe') end it "should generate password when forcing random password" do - Devise.stub(:friendly_token).and_return('123456789') + allow(Devise).to receive(:friendly_token).and_return('123456789') user = create(:user, password: 'abcdefg', force_random_password: true) - user.password.should == '12345678' + expect(user.password).to eq('12345678') end end describe 'authentication token' do it "should have authentication token" do user = create(:user) - user.authentication_token.should_not be_blank + expect(user.authentication_token).not_to be_blank end end @@ -152,15 +158,15 @@ describe User do @project_3.team << [@user, :developer] end - it { @user.authorized_projects.should include(@project) } - it { @user.authorized_projects.should include(@project_2) } - it { @user.authorized_projects.should include(@project_3) } - it { @user.owned_projects.should include(@project) } - it { @user.owned_projects.should_not include(@project_2) } - it { @user.owned_projects.should_not include(@project_3) } - it { @user.personal_projects.should include(@project) } - it { @user.personal_projects.should_not include(@project_2) } - it { @user.personal_projects.should_not include(@project_3) } + it { expect(@user.authorized_projects).to include(@project) } + it { expect(@user.authorized_projects).to include(@project_2) } + it { expect(@user.authorized_projects).to include(@project_3) } + it { expect(@user.owned_projects).to include(@project) } + it { expect(@user.owned_projects).not_to include(@project_2) } + it { expect(@user.owned_projects).not_to include(@project_3) } + it { expect(@user.personal_projects).to include(@project) } + it { expect(@user.personal_projects).not_to include(@project_2) } + it { expect(@user.personal_projects).not_to include(@project_3) } end describe 'groups' do @@ -170,9 +176,9 @@ describe User do @group.add_owner(@user) end - it { @user.several_namespaces?.should be_true } - it { @user.authorized_groups.should == [@group] } - it { @user.owned_groups.should == [@group] } + it { expect(@user.several_namespaces?).to be_truthy } + it { expect(@user.authorized_groups).to eq([@group]) } + it { expect(@user.owned_groups).to eq([@group]) } end describe 'group multiple owners' do @@ -185,7 +191,7 @@ describe User do @group.add_user(@user2, GroupMember::OWNER) end - it { @user2.several_namespaces?.should be_true } + it { expect(@user2.several_namespaces?).to be_truthy } end describe 'namespaced' do @@ -194,7 +200,7 @@ describe User do @project = create :project, namespace: @user.namespace end - it { @user.several_namespaces?.should be_false } + it { expect(@user.several_namespaces?).to be_falsey } end describe 'blocking user' do @@ -202,7 +208,7 @@ describe User do it "should block user" do user.block - user.blocked?.should be_true + expect(user.blocked?).to be_truthy end end @@ -214,10 +220,10 @@ describe User do @blocked = create :user, state: :blocked end - it { User.filter("admins").should == [@admin] } - it { User.filter("blocked").should == [@blocked] } - it { User.filter("wop").should include(@user, @admin, @blocked) } - it { User.filter(nil).should include(@user, @admin) } + it { expect(User.filter("admins")).to eq([@admin]) } + it { expect(User.filter("blocked")).to eq([@blocked]) } + it { expect(User.filter("wop")).to include(@user, @admin, @blocked) } + it { expect(User.filter(nil)).to include(@user, @admin) } end describe :not_in_project do @@ -227,27 +233,27 @@ describe User do @project = create :project end - it { User.not_in_project(@project).should include(@user, @project.owner) } + it { expect(User.not_in_project(@project)).to include(@user, @project.owner) } end describe 'user creation' do describe 'normal user' do let(:user) { create(:user, name: 'John Smith') } - it { user.is_admin?.should be_false } - it { user.require_ssh_key?.should be_true } - it { user.can_create_group?.should be_true } - it { user.can_create_project?.should be_true } - it { user.first_name.should == 'John' } + it { expect(user.is_admin?).to be_falsey } + it { expect(user.require_ssh_key?).to be_truthy } + it { expect(user.can_create_group?).to be_truthy } + it { expect(user.can_create_project?).to be_truthy } + it { expect(user.first_name).to eq('John') } end describe 'with defaults' do let(:user) { User.new } it "should apply defaults to user" do - user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit - user.can_create_group.should == Gitlab.config.gitlab.default_can_create_group - user.theme_id.should == Gitlab.config.gitlab.default_theme + expect(user.projects_limit).to eq(Gitlab.config.gitlab.default_projects_limit) + expect(user.can_create_group).to eq(Gitlab.config.gitlab.default_can_create_group) + expect(user.theme_id).to eq(Gitlab.config.gitlab.default_theme) end end @@ -255,9 +261,9 @@ describe User do let(:user) { User.new(projects_limit: 123, can_create_group: false, can_create_team: true, theme_id: Gitlab::Theme::BASIC) } it "should apply defaults to user" do - user.projects_limit.should == 123 - user.can_create_group.should be_false - user.theme_id.should == Gitlab::Theme::BASIC + expect(user.projects_limit).to eq(123) + expect(user.can_create_group).to be_falsey + expect(user.theme_id).to eq(Gitlab::Theme::BASIC) end end end @@ -267,12 +273,12 @@ describe User do let(:user2) { create(:user, username: 'jameson', email: 'jameson@example.com') } it "should be case insensitive" do - User.search(user1.username.upcase).to_a.should == [user1] - User.search(user1.username.downcase).to_a.should == [user1] - User.search(user2.username.upcase).to_a.should == [user2] - User.search(user2.username.downcase).to_a.should == [user2] - User.search(user1.username.downcase).to_a.count.should == 2 - User.search(user2.username.downcase).to_a.count.should == 1 + expect(User.search(user1.username.upcase).to_a).to eq([user1]) + expect(User.search(user1.username.downcase).to_a).to eq([user1]) + expect(User.search(user2.username.upcase).to_a).to eq([user2]) + expect(User.search(user2.username.downcase).to_a).to eq([user2]) + expect(User.search(user1.username.downcase).to_a.count).to eq(2) + expect(User.search(user2.username.downcase).to_a.count).to eq(1) end end @@ -280,21 +286,45 @@ describe User do let(:user1) { create(:user, username: 'foo') } it "should get the correct user" do - User.by_username_or_id(user1.id).should == user1 - User.by_username_or_id('foo').should == user1 - User.by_username_or_id(-1).should be_nil - User.by_username_or_id('bar').should be_nil + expect(User.by_username_or_id(user1.id)).to eq(user1) + expect(User.by_username_or_id('foo')).to eq(user1) + expect(User.by_username_or_id(-1)).to be_nil + expect(User.by_username_or_id('bar')).to be_nil + end + end + + describe '.by_login' do + let(:username) { 'John' } + let!(:user) { create(:user, username: username) } + + it 'should get the correct user' do + expect(User.by_login(user.email.upcase)).to eq user + expect(User.by_login(user.email)).to eq user + expect(User.by_login(username.downcase)).to eq user + expect(User.by_login(username)).to eq user + expect(User.by_login(nil)).to be_nil + expect(User.by_login('')).to be_nil + end + end + + describe ".clean_username" do + + let!(:user) { create(:user, username: "johngitlab-etc") } + let!(:namespace) { create(:namespace, path: "JohnGitLab-etc1") } + + it "cleans a username and makes sure it's available" do + expect(User.clean_username("-john+gitlab-ETC%.git@gmail.com")).to eq("johngitlab-ETC2") end end describe 'all_ssh_keys' do - it { should have_many(:keys).dependent(:destroy) } + it { is_expected.to have_many(:keys).dependent(:destroy) } it "should have all ssh keys" do user = create :user key = create :key, key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD33bWLBxu48Sev9Fert1yzEO4WGcWglWF7K/AwblIUFselOt/QdOL9DSjpQGxLagO1s9wl53STIO8qGS4Ms0EJZyIXOEFMjFJ5xmjSy+S37By4sG7SsltQEHMxtbtFOaW5LV2wCrX+rUsRNqLMamZjgjcPO0/EgGCXIGMAYW4O7cwGZdXWYIhQ1Vwy+CsVMDdPkPgBXqK7nR/ey8KMs8ho5fMNgB5hBw/AL9fNGhRw3QTD6Q12Nkhl4VZES2EsZqlpNnJttnPdp847DUsT6yuLRlfiQfz5Cn9ysHFdXObMN5VYIiPFwHeYCZp1X2S4fDZooRE8uOLTfxWHPXwrhqSH", user_id: user.id - user.all_ssh_keys.should include(key.key) + expect(user.all_ssh_keys).to include(key.key) end end @@ -303,12 +333,12 @@ describe User do it "should be true if avatar is image" do user.update_attribute(:avatar, 'uploads/avatar.png') - user.avatar_type.should be_true + expect(user.avatar_type).to be_truthy end it "should be false if avatar is html page" do user.update_attribute(:avatar, 'uploads/avatar.html') - user.avatar_type.should == ["only images allowed"] + expect(user.avatar_type).to eq(["only images allowed"]) end end @@ -319,7 +349,7 @@ describe User do # Create a condition which would otherwise cause 'true' to be returned user.stub(ldap_user?: true) user.last_credential_check_at = nil - expect(user.requires_ldap_check?).to be_false + expect(user.requires_ldap_check?).to be_falsey end context 'when LDAP is enabled' do @@ -327,7 +357,7 @@ describe User do it 'is false for non-LDAP users' do user.stub(ldap_user?: false) - expect(user.requires_ldap_check?).to be_false + expect(user.requires_ldap_check?).to be_falsey end context 'and when the user is an LDAP user' do @@ -335,17 +365,41 @@ describe User do it 'is true when the user has never had an LDAP check before' do user.last_credential_check_at = nil - expect(user.requires_ldap_check?).to be_true + expect(user.requires_ldap_check?).to be_truthy end it 'is true when the last LDAP check happened over 1 hour ago' do user.last_credential_check_at = 2.hours.ago - expect(user.requires_ldap_check?).to be_true + expect(user.requires_ldap_check?).to be_truthy end end end end + describe :ldap_user? do + it "is true if provider name starts with ldap" do + user = create(:omniauth_user, provider: 'ldapmain') + expect( user.ldap_user? ).to be_truthy + end + + it "is false for other providers" do + user = create(:omniauth_user, provider: 'other-provider') + expect( user.ldap_user? ).to be_falsey + end + + it "is false if no extern_uid is provided" do + user = create(:omniauth_user, extern_uid: nil) + expect( user.ldap_user? ).to be_falsey + end + end + + describe :ldap_identity do + it "returns ldap identity" do + user = create :omniauth_user + expect(user.ldap_identity.provider).not_to be_empty + end + end + describe '#full_website_url' do let(:user) { create(:user) } @@ -396,24 +450,24 @@ describe User do project1 = create :project, :public project2 = create :project, :public - expect(user.starred?(project1)).to be_false - expect(user.starred?(project2)).to be_false + expect(user.starred?(project1)).to be_falsey + expect(user.starred?(project2)).to be_falsey star1 = UsersStarProject.create!(project: project1, user: user) - expect(user.starred?(project1)).to be_true - expect(user.starred?(project2)).to be_false + expect(user.starred?(project1)).to be_truthy + expect(user.starred?(project2)).to be_falsey star2 = UsersStarProject.create!(project: project2, user: user) - expect(user.starred?(project1)).to be_true - expect(user.starred?(project2)).to be_true + expect(user.starred?(project1)).to be_truthy + expect(user.starred?(project2)).to be_truthy star1.destroy - expect(user.starred?(project1)).to be_false - expect(user.starred?(project2)).to be_true + expect(user.starred?(project1)).to be_falsey + expect(user.starred?(project2)).to be_truthy star2.destroy - expect(user.starred?(project1)).to be_false - expect(user.starred?(project2)).to be_false + expect(user.starred?(project1)).to be_falsey + expect(user.starred?(project2)).to be_falsey end end @@ -422,11 +476,67 @@ describe User do user = create :user project = create :project, :public - expect(user.starred?(project)).to be_false + expect(user.starred?(project)).to be_falsey user.toggle_star(project) - expect(user.starred?(project)).to be_true + expect(user.starred?(project)).to be_truthy user.toggle_star(project) - expect(user.starred?(project)).to be_false + expect(user.starred?(project)).to be_falsey + end + end + + describe "#sort" do + before do + User.delete_all + @user = create :user, created_at: Date.today, last_sign_in_at: Date.today, name: 'Alpha' + @user1 = create :user, created_at: Date.today - 1, last_sign_in_at: Date.today - 1, name: 'Omega' + end + + it "sorts users as recently_signed_in" do + expect(User.sort('recent_sign_in').first).to eq(@user) + end + + it "sorts users as late_signed_in" do + expect(User.sort('oldest_sign_in').first).to eq(@user1) + end + + it "sorts users as recently_created" do + expect(User.sort('created_desc').first).to eq(@user) + end + + it "sorts users as late_created" do + expect(User.sort('created_asc').first).to eq(@user1) + end + + it "sorts users by name when nil is passed" do + expect(User.sort(nil).first).to eq(@user) + end + end + + describe "#contributed_projects_ids" do + + subject { create(:user) } + let!(:project1) { create(:project) } + let!(:project2) { create(:project, forked_from_project: project3) } + let!(:project3) { create(:project) } + let!(:merge_request) { create(:merge_request, source_project: project2, target_project: project3, author: subject) } + let!(:push_event) { create(:event, action: Event::PUSHED, project: project1, target: project1, author: subject) } + let!(:merge_event) { create(:event, action: Event::CREATED, project: project3, target: merge_request, author: subject) } + + before do + project1.team << [subject, :master] + project2.team << [subject, :master] + end + + it "includes IDs for projects the user has pushed to" do + expect(subject.contributed_projects_ids).to include(project1.id) + end + + it "includes IDs for projects the user has had merge requests merged into" do + expect(subject.contributed_projects_ids).to include(project3.id) + end + + it "doesn't include IDs for unrelated projects" do + expect(subject.contributed_projects_ids).not_to include(project2.id) end end end diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index d065431ee3a..f3fd805783f 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -16,27 +16,27 @@ describe WikiPage do end it "sets the slug attribute" do - @wiki_page.slug.should == "test-page" + expect(@wiki_page.slug).to eq("test-page") end it "sets the title attribute" do - @wiki_page.title.should == "test page" + expect(@wiki_page.title).to eq("test page") end it "sets the formatted content attribute" do - @wiki_page.content.should == "test content" + expect(@wiki_page.content).to eq("test content") end it "sets the format attribute" do - @wiki_page.format.should == :markdown + expect(@wiki_page.format).to eq(:markdown) end it "sets the message attribute" do - @wiki_page.message.should == "test commit" + expect(@wiki_page.message).to eq("test commit") end it "sets the version attribute" do - @wiki_page.version.should be_a Grit::Commit + expect(@wiki_page.version).to be_a Gollum::Git::Commit end end end @@ -48,12 +48,12 @@ describe WikiPage do it "validates presence of title" do subject.attributes.delete(:title) - subject.valid?.should be_false + expect(subject.valid?).to be_falsey end it "validates presence of content" do subject.attributes.delete(:content) - subject.valid?.should be_false + expect(subject.valid?).to be_falsey end end @@ -69,11 +69,11 @@ describe WikiPage do context "with valid attributes" do it "saves the wiki page" do subject.create(@wiki_attr) - wiki.find_page("Index").should_not be_nil + expect(wiki.find_page("Index")).not_to be_nil end it "returns true" do - subject.create(@wiki_attr).should == true + expect(subject.create(@wiki_attr)).to eq(true) end end end @@ -95,7 +95,7 @@ describe WikiPage do end it "returns true" do - @page.update("more content").should be_true + expect(@page.update("more content")).to be_truthy end end end @@ -108,11 +108,11 @@ describe WikiPage do it "should delete the page" do @page.delete - wiki.pages.should be_empty + expect(wiki.pages).to be_empty end it "should return true" do - @page.delete.should == true + expect(@page.delete).to eq(true) end end @@ -128,7 +128,7 @@ describe WikiPage do it "returns an array of all commits for the page" do 3.times { |i| @page.update("content #{i}") } - @page.versions.count.should == 4 + expect(@page.versions.count).to eq(4) end end @@ -144,7 +144,7 @@ describe WikiPage do it "should be replace a hyphen to a space" do @page.title = "Import-existing-repositories-into-GitLab" - @page.title.should == "Import existing repositories into GitLab" + expect(@page.title).to eq("Import existing repositories into GitLab") end end diff --git a/spec/requests/api/api_helpers_spec.rb b/spec/requests/api/api_helpers_spec.rb index e2f222c0d34..20cb30a39bb 100644 --- a/spec/requests/api/api_helpers_spec.rb +++ b/spec/requests/api/api_helpers_spec.rb @@ -41,32 +41,33 @@ describe API, api: true do describe ".current_user" do it "should return nil for an invalid token" do env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = 'invalid token' - current_user.should be_nil + allow_any_instance_of(self.class).to receive(:doorkeeper_guard){ false } + expect(current_user).to be_nil end it "should return nil for a user without access" do env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token Gitlab::UserAccess.stub(allowed?: false) - current_user.should be_nil + expect(current_user).to be_nil end it "should leave user as is when sudo not specified" do env[API::APIHelpers::PRIVATE_TOKEN_HEADER] = user.private_token - current_user.should == user + expect(current_user).to eq(user) clear_env params[API::APIHelpers::PRIVATE_TOKEN_PARAM] = user.private_token - current_user.should == user + expect(current_user).to eq(user) end it "should change current user to sudo when admin" do set_env(admin, user.id) - current_user.should == user + expect(current_user).to eq(user) set_param(admin, user.id) - current_user.should == user + expect(current_user).to eq(user) set_env(admin, user.username) - current_user.should == user + expect(current_user).to eq(user) set_param(admin, user.username) - current_user.should == user + expect(current_user).to eq(user) end it "should throw an error when the current user is not an admin and attempting to sudo" do @@ -82,8 +83,8 @@ describe API, api: true do it "should throw an error when the user cannot be found for a given id" do id = user.id + admin.id - user.id.should_not == id - admin.id.should_not == id + expect(user.id).not_to eq(id) + expect(admin.id).not_to eq(id) set_env(admin, id) expect { current_user }.to raise_error @@ -93,8 +94,8 @@ describe API, api: true do it "should throw an error when the user cannot be found for a given username" do username = "#{user.username}#{admin.username}" - user.username.should_not == username - admin.username.should_not == username + expect(user.username).not_to eq(username) + expect(admin.username).not_to eq(username) set_env(admin, username) expect { current_user }.to raise_error @@ -104,69 +105,69 @@ describe API, api: true do it "should handle sudo's to oneself" do set_env(admin, admin.id) - current_user.should == admin + expect(current_user).to eq(admin) set_param(admin, admin.id) - current_user.should == admin + expect(current_user).to eq(admin) set_env(admin, admin.username) - current_user.should == admin + expect(current_user).to eq(admin) set_param(admin, admin.username) - current_user.should == admin + expect(current_user).to eq(admin) end it "should handle multiple sudo's to oneself" do set_env(admin, user.id) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) set_env(admin, user.username) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) set_param(admin, user.id) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) set_param(admin, user.username) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) end it "should handle multiple sudo's to oneself using string ids" do set_env(admin, user.id.to_s) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) set_param(admin, user.id.to_s) - current_user.should == user - current_user.should == user + expect(current_user).to eq(user) + expect(current_user).to eq(user) end end describe '.sudo_identifier' do it "should return integers when input is an int" do set_env(admin, '123') - sudo_identifier.should == 123 + expect(sudo_identifier).to eq(123) set_env(admin, '0001234567890') - sudo_identifier.should == 1234567890 + expect(sudo_identifier).to eq(1234567890) set_param(admin, '123') - sudo_identifier.should == 123 + expect(sudo_identifier).to eq(123) set_param(admin, '0001234567890') - sudo_identifier.should == 1234567890 + expect(sudo_identifier).to eq(1234567890) end it "should return string when input is an is not an int" do set_env(admin, '12.30') - sudo_identifier.should == "12.30" + expect(sudo_identifier).to eq("12.30") set_env(admin, 'hello') - sudo_identifier.should == 'hello' + expect(sudo_identifier).to eq('hello') set_env(admin, ' 123') - sudo_identifier.should == ' 123' + expect(sudo_identifier).to eq(' 123') set_param(admin, '12.30') - sudo_identifier.should == "12.30" + expect(sudo_identifier).to eq("12.30") set_param(admin, 'hello') - sudo_identifier.should == 'hello' + expect(sudo_identifier).to eq('hello') set_param(admin, ' 123') - sudo_identifier.should == ' 123' + expect(sudo_identifier).to eq(' 123') end end end diff --git a/spec/requests/api/branches_spec.rb b/spec/requests/api/branches_spec.rb index 8834a6cfa83..f40d68b75a4 100644 --- a/spec/requests/api/branches_spec.rb +++ b/spec/requests/api/branches_spec.rb @@ -15,79 +15,79 @@ describe API::API, api: true do describe "GET /projects/:id/repository/branches" do it "should return an array of project branches" do get api("/projects/#{project.id}/repository/branches", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['name'].should == project.repository.branch_names.first + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(project.repository.branch_names.first) end end describe "GET /projects/:id/repository/branches/:branch" do it "should return the branch information for a single branch" do get api("/projects/#{project.id}/repository/branches/#{branch_name}", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response['name'].should == branch_name - json_response['commit']['id'].should == branch_sha - json_response['protected'].should == false + expect(json_response['name']).to eq(branch_name) + expect(json_response['commit']['id']).to eq(branch_sha) + expect(json_response['protected']).to eq(false) end it "should return a 403 error if guest" do get api("/projects/#{project.id}/repository/branches", user2) - response.status.should == 403 + expect(response.status).to eq(403) end it "should return a 404 error if branch is not available" do get api("/projects/#{project.id}/repository/branches/unknown", user) - response.status.should == 404 + expect(response.status).to eq(404) end end describe "PUT /projects/:id/repository/branches/:branch/protect" do it "should protect a single branch" do put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response['name'].should == branch_name - json_response['commit']['id'].should == branch_sha - json_response['protected'].should == true + expect(json_response['name']).to eq(branch_name) + expect(json_response['commit']['id']).to eq(branch_sha) + expect(json_response['protected']).to eq(true) end it "should return a 404 error if branch not found" do put api("/projects/#{project.id}/repository/branches/unknown/protect", user) - response.status.should == 404 + expect(response.status).to eq(404) end it "should return a 403 error if guest" do put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user2) - response.status.should == 403 + expect(response.status).to eq(403) end it "should return success when protect branch again" do put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) put api("/projects/#{project.id}/repository/branches/#{branch_name}/protect", user) - response.status.should == 200 + expect(response.status).to eq(200) end end describe "PUT /projects/:id/repository/branches/:branch/unprotect" do it "should unprotect a single branch" do put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response['name'].should == branch_name - json_response['commit']['id'].should == branch_sha - json_response['protected'].should == false + expect(json_response['name']).to eq(branch_name) + expect(json_response['commit']['id']).to eq(branch_sha) + expect(json_response['protected']).to eq(false) end it "should return success when unprotect branch" do put api("/projects/#{project.id}/repository/branches/unknown/unprotect", user) - response.status.should == 404 + expect(response.status).to eq(404) end it "should return success when unprotect branch again" do put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) put api("/projects/#{project.id}/repository/branches/#{branch_name}/unprotect", user) - response.status.should == 200 + expect(response.status).to eq(200) end end @@ -97,46 +97,46 @@ describe API::API, api: true do branch_name: 'feature1', ref: branch_sha - response.status.should == 201 + expect(response.status).to eq(201) - json_response['name'].should == 'feature1' - json_response['commit']['id'].should == branch_sha + expect(json_response['name']).to eq('feature1') + expect(json_response['commit']['id']).to eq(branch_sha) end it "should deny for user without push access" do post api("/projects/#{project.id}/repository/branches", user2), branch_name: branch_name, ref: branch_sha - response.status.should == 403 + expect(response.status).to eq(403) end it 'should return 400 if branch name is invalid' do post api("/projects/#{project.id}/repository/branches", user), branch_name: 'new design', ref: branch_sha - response.status.should == 400 - json_response['message'].should == 'Branch name invalid' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Branch name invalid') end it 'should return 400 if branch already exists' do post api("/projects/#{project.id}/repository/branches", user), branch_name: 'new_design1', ref: branch_sha - response.status.should == 201 + expect(response.status).to eq(201) post api("/projects/#{project.id}/repository/branches", user), branch_name: 'new_design1', ref: branch_sha - response.status.should == 400 - json_response['message'].should == 'Branch already exists' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Branch already exists') end it 'should return 400 if ref name is invalid' do post api("/projects/#{project.id}/repository/branches", user), branch_name: 'new_design3', ref: 'foo' - response.status.should == 400 - json_response['message'].should == 'Invalid reference name' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Invalid reference name') end end @@ -145,25 +145,26 @@ describe API::API, api: true do it "should remove branch" do delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user) - response.status.should == 200 + expect(response.status).to eq(200) + expect(json_response['branch_name']).to eq(branch_name) end it 'should return 404 if branch not exists' do delete api("/projects/#{project.id}/repository/branches/foobar", user) - response.status.should == 404 + expect(response.status).to eq(404) end it "should remove protected branch" do project.protected_branches.create(name: branch_name) delete api("/projects/#{project.id}/repository/branches/#{branch_name}", user) - response.status.should == 405 - json_response['message'].should == 'Protected branch cant be removed' + expect(response.status).to eq(405) + expect(json_response['message']).to eq('Protected branch cant be removed') end it "should not remove HEAD branch" do delete api("/projects/#{project.id}/repository/branches/master", user) - response.status.should == 405 - json_response['message'].should == 'Cannot remove HEAD branch' + expect(response.status).to eq(405) + expect(json_response['message']).to eq('Cannot remove HEAD branch') end end end diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb index 38e0a284c36..9ea60e1a4ad 100644 --- a/spec/requests/api/commits_spec.rb +++ b/spec/requests/api/commits_spec.rb @@ -8,6 +8,7 @@ describe API::API, api: true do let!(:project) { create(:project, creator_id: user.id) } let!(:master) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } let!(:guest) { create(:project_member, user: user2, project: project, access_level: ProjectMember::GUEST) } + let!(:note) { create(:note_on_commit, author: user, project: project, commit_id: project.repository.commit.id, note: 'a comment on a commit') } before { project.team << [user, :reporter] } @@ -17,17 +18,17 @@ describe API::API, api: true do it "should return project commits" do get api("/projects/#{project.id}/repository/commits", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response.should be_an Array - json_response.first['id'].should == project.repository.commit.id + expect(json_response).to be_an Array + expect(json_response.first['id']).to eq(project.repository.commit.id) end end context "unauthorized user" do it "should not return project commits" do get api("/projects/#{project.id}/repository/commits") - response.status.should == 401 + expect(response.status).to eq(401) end end end @@ -36,21 +37,21 @@ describe API::API, api: true do context "authorized user" do it "should return a commit by sha" do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}", user) - response.status.should == 200 - json_response['id'].should == project.repository.commit.id - json_response['title'].should == project.repository.commit.title + expect(response.status).to eq(200) + expect(json_response['id']).to eq(project.repository.commit.id) + expect(json_response['title']).to eq(project.repository.commit.title) end it "should return a 404 error if not found" do get api("/projects/#{project.id}/repository/commits/invalid_sha", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "unauthorized user" do it "should not return the selected commit" do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}") - response.status.should == 401 + expect(response.status).to eq(401) end end end @@ -61,23 +62,87 @@ describe API::API, api: true do it "should return the diff of the selected commit" do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response.should be_an Array - json_response.length.should >= 1 - json_response.first.keys.should include "diff" + expect(json_response).to be_an Array + expect(json_response.length).to be >= 1 + expect(json_response.first.keys).to include "diff" end it "should return a 404 error if invalid commit" do get api("/projects/#{project.id}/repository/commits/invalid_sha/diff", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "unauthorized user" do it "should not return the diff of the selected commit" do get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/diff") - response.status.should == 401 + expect(response.status).to eq(401) + end + end + end + + describe 'GET /projects:id/repository/commits/:sha/comments' do + context 'authorized user' do + it 'should return merge_request comments' do + get api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['note']).to eq('a comment on a commit') + expect(json_response.first['author']['id']).to eq(user.id) + end + + it 'should return a 404 error if merge_request_id not found' do + get api("/projects/#{project.id}/repository/commits/1234ab/comments", user) + expect(response.status).to eq(404) + end + end + + context 'unauthorized user' do + it 'should not return the diff of the selected commit' do + get api("/projects/#{project.id}/repository/commits/1234ab/comments") + expect(response.status).to eq(401) + end + end + end + + describe 'POST /projects:id/repository/commits/:sha/comments' do + context 'authorized user' do + it 'should return comment' do + post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment' + expect(response.status).to eq(201) + expect(json_response['note']).to eq('My comment') + expect(json_response['path']).to be_nil + expect(json_response['line']).to be_nil + expect(json_response['line_type']).to be_nil + end + + it 'should return the inline comment' do + post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user), note: 'My comment', path: project.repository.commit.diffs.first.new_path, line: 7, line_type: 'new' + expect(response.status).to eq(201) + expect(json_response['note']).to eq('My comment') + expect(json_response['path']).to eq(project.repository.commit.diffs.first.new_path) + expect(json_response['line']).to eq(7) + expect(json_response['line_type']).to eq('new') + end + + it 'should return 400 if note is missing' do + post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments", user) + expect(response.status).to eq(400) + end + + it 'should return 404 if note is attached to non existent commit' do + post api("/projects/#{project.id}/repository/commits/1234ab/comments", user), note: 'My comment' + expect(response.status).to eq(404) + end + end + + context 'unauthorized user' do + it 'should not return the diff of the selected commit' do + post api("/projects/#{project.id}/repository/commits/#{project.repository.commit.id}/comments") + expect(response.status).to eq(401) end end end diff --git a/spec/requests/api/doorkeeper_access_spec.rb b/spec/requests/api/doorkeeper_access_spec.rb new file mode 100644 index 00000000000..39949a90422 --- /dev/null +++ b/spec/requests/api/doorkeeper_access_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let!(:user) { create(:user) } + let!(:application) { Doorkeeper::Application.create!(:name => "MyApp", :redirect_uri => "https://app.com", :owner => user) } + let!(:token) { Doorkeeper::AccessToken.create! :application_id => application.id, :resource_owner_id => user.id } + + + describe "when unauthenticated" do + it "returns authentication success" do + get api("/user"), :access_token => token.token + expect(response.status).to eq(200) + end + end + + describe "when token invalid" do + it "returns authentication error" do + get api("/user"), :access_token => "123a" + expect(response.status).to eq(401) + end + end + + describe "authorization by private token" do + it "returns authentication success" do + get api("/user", user) + expect(response.status).to eq(200) + end + end +end diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index b43a202aec0..bab8888a631 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -16,15 +16,15 @@ describe API::API, api: true do } get api("/projects/#{project.id}/repository/files", user), params - response.status.should == 200 - json_response['file_path'].should == file_path - json_response['file_name'].should == 'popen.rb' - Base64.decode64(json_response['content']).lines.first.should == "require 'fileutils'\n" + expect(response.status).to eq(200) + expect(json_response['file_path']).to eq(file_path) + expect(json_response['file_name']).to eq('popen.rb') + expect(Base64.decode64(json_response['content']).lines.first).to eq("require 'fileutils'\n") end it "should return a 400 bad request if no params given" do get api("/projects/#{project.id}/repository/files", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 404 if such file does not exist" do @@ -34,7 +34,7 @@ describe API::API, api: true do } get api("/projects/#{project.id}/repository/files", user), params - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -54,13 +54,13 @@ describe API::API, api: true do ) post api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 201 - json_response['file_path'].should == 'newfile.rb' + expect(response.status).to eq(201) + expect(json_response['file_path']).to eq('newfile.rb') end it "should return a 400 bad request if no params given" do post api("/projects/#{project.id}/repository/files", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 400 if satellite fails to create file" do @@ -69,7 +69,7 @@ describe API::API, api: true do ) post api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 400 + expect(response.status).to eq(400) end end @@ -89,22 +89,42 @@ describe API::API, api: true do ) put api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 200 - json_response['file_path'].should == file_path + expect(response.status).to eq(200) + expect(json_response['file_path']).to eq(file_path) end it "should return a 400 bad request if no params given" do put api("/projects/#{project.id}/repository/files", user) - response.status.should == 400 + expect(response.status).to eq(400) end - it "should return a 400 if satellite fails to create file" do - Gitlab::Satellite::EditFileAction.any_instance.stub( - commit!: false, - ) + it 'should return a 400 if the checkout fails' do + Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!) + .and_raise(Gitlab::Satellite::CheckoutFailed) + + put api("/projects/#{project.id}/repository/files", user), valid_params + expect(response.status).to eq(400) + + ref = valid_params[:branch_name] + expect(response.body).to match("ref '#{ref}' could not be checked out") + end + + it 'should return a 409 if the file was not modified' do + Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!) + .and_raise(Gitlab::Satellite::CommitFailed) + + put api("/projects/#{project.id}/repository/files", user), valid_params + expect(response.status).to eq(409) + expect(response.body).to match("Maybe there was nothing to commit?") + end + + it 'should return a 409 if the push fails' do + Gitlab::Satellite::EditFileAction.any_instance.stub(:commit!) + .and_raise(Gitlab::Satellite::PushFailed) put api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 400 + expect(response.status).to eq(409) + expect(response.body).to match("Maybe the file was changed by another process?") end end @@ -123,13 +143,13 @@ describe API::API, api: true do ) delete api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 200 - json_response['file_path'].should == file_path + expect(response.status).to eq(200) + expect(json_response['file_path']).to eq(file_path) end it "should return a 400 bad request if no params given" do delete api("/projects/#{project.id}/repository/files", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 400 if satellite fails to create file" do @@ -138,7 +158,7 @@ describe API::API, api: true do ) delete api("/projects/#{project.id}/repository/files", user), valid_params - response.status.should == 400 + expect(response.status).to eq(400) end end end diff --git a/spec/requests/api/fork_spec.rb b/spec/requests/api/fork_spec.rb index cbbd1e7de5a..fb3ff552c8d 100644 --- a/spec/requests/api/fork_spec.rb +++ b/spec/requests/api/fork_spec.rb @@ -23,50 +23,50 @@ describe API::API, api: true do context 'when authenticated' do it 'should fork if user has sufficient access to project' do post api("/projects/fork/#{project.id}", user2) - response.status.should == 201 - json_response['name'].should == project.name - json_response['path'].should == project.path - json_response['owner']['id'].should == user2.id - json_response['namespace']['id'].should == user2.namespace.id - json_response['forked_from_project']['id'].should == project.id + expect(response.status).to eq(201) + expect(json_response['name']).to eq(project.name) + expect(json_response['path']).to eq(project.path) + expect(json_response['owner']['id']).to eq(user2.id) + expect(json_response['namespace']['id']).to eq(user2.namespace.id) + expect(json_response['forked_from_project']['id']).to eq(project.id) end it 'should fork if user is admin' do post api("/projects/fork/#{project.id}", admin) - response.status.should == 201 - json_response['name'].should == project.name - json_response['path'].should == project.path - json_response['owner']['id'].should == admin.id - json_response['namespace']['id'].should == admin.namespace.id - json_response['forked_from_project']['id'].should == project.id + expect(response.status).to eq(201) + expect(json_response['name']).to eq(project.name) + expect(json_response['path']).to eq(project.path) + expect(json_response['owner']['id']).to eq(admin.id) + expect(json_response['namespace']['id']).to eq(admin.namespace.id) + expect(json_response['forked_from_project']['id']).to eq(project.id) end it 'should fail on missing project access for the project to fork' do post api("/projects/fork/#{project.id}", user3) - response.status.should == 404 - json_response['message'].should == '404 Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Project Not Found') end it 'should fail if forked project exists in the user namespace' do post api("/projects/fork/#{project.id}", user) - response.status.should == 409 - json_response['message']['base'].should == ['Invalid fork destination'] - json_response['message']['name'].should == ['has already been taken'] - json_response['message']['path'].should == ['has already been taken'] + expect(response.status).to eq(409) + expect(json_response['message']['base']).to eq(['Invalid fork destination']) + expect(json_response['message']['name']).to eq(['has already been taken']) + expect(json_response['message']['path']).to eq(['has already been taken']) end it 'should fail if project to fork from does not exist' do post api('/projects/fork/424242', user) - response.status.should == 404 - json_response['message'].should == '404 Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Project Not Found') end end context 'when unauthenticated' do it 'should return authentication error' do post api("/projects/fork/#{project.id}") - response.status.should == 401 - json_response['message'].should == '401 Unauthorized' + expect(response.status).to eq(401) + expect(json_response['message']).to eq('401 Unauthorized') end end end diff --git a/spec/requests/api/group_members_spec.rb b/spec/requests/api/group_members_spec.rb new file mode 100644 index 00000000000..8ba6876a95b --- /dev/null +++ b/spec/requests/api/group_members_spec.rb @@ -0,0 +1,199 @@ +require 'spec_helper' + +describe API::API, api: true do + include ApiHelpers + + let(:owner) { create(:user) } + let(:reporter) { create(:user) } + let(:developer) { create(:user) } + let(:master) { create(:user) } + let(:guest) { create(:user) } + let(:stranger) { create(:user) } + + let!(:group_with_members) do + group = create(:group) + group.add_users([reporter.id], GroupMember::REPORTER) + group.add_users([developer.id], GroupMember::DEVELOPER) + group.add_users([master.id], GroupMember::MASTER) + group.add_users([guest.id], GroupMember::GUEST) + group + end + + let!(:group_no_members) { create(:group) } + + before do + group_with_members.add_owner owner + group_no_members.add_owner owner + end + + describe "GET /groups/:id/members" do + context "when authenticated as user that is part or the group" do + it "each user: should return an array of members groups of group3" do + [owner, master, developer, reporter, guest].each do |user| + get api("/groups/#{group_with_members.id}/members", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(5) + expect(json_response.find { |e| e['id']==owner.id }['access_level']).to eq(GroupMember::OWNER) + expect(json_response.find { |e| e['id']==reporter.id }['access_level']).to eq(GroupMember::REPORTER) + expect(json_response.find { |e| e['id']==developer.id }['access_level']).to eq(GroupMember::DEVELOPER) + expect(json_response.find { |e| e['id']==master.id }['access_level']).to eq(GroupMember::MASTER) + expect(json_response.find { |e| e['id']==guest.id }['access_level']).to eq(GroupMember::GUEST) + end + end + + it "users not part of the group should get access error" do + get api("/groups/#{group_with_members.id}/members", stranger) + expect(response.status).to eq(403) + end + end + end + + describe "POST /groups/:id/members" do + context "when not a member of the group" do + it "should not add guest as member of group_no_members when adding being done by person outside the group" do + post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: GroupMember::MASTER + expect(response.status).to eq(403) + end + end + + context "when a member of the group" do + it "should return ok and add new member" do + new_user = create(:user) + + expect { + post api("/groups/#{group_no_members.id}/members", owner), + user_id: new_user.id, access_level: GroupMember::MASTER + }.to change { group_no_members.members.count }.by(1) + + expect(response.status).to eq(201) + expect(json_response['name']).to eq(new_user.name) + expect(json_response['access_level']).to eq(GroupMember::MASTER) + end + + it "should not allow guest to modify group members" do + new_user = create(:user) + + expect { + post api("/groups/#{group_with_members.id}/members", guest), + user_id: new_user.id, access_level: GroupMember::MASTER + }.not_to change { group_with_members.members.count } + + expect(response.status).to eq(403) + end + + it "should return error if member already exists" do + post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: GroupMember::MASTER + expect(response.status).to eq(409) + end + + it "should return a 400 error when user id is not given" do + post api("/groups/#{group_no_members.id}/members", owner), access_level: GroupMember::MASTER + expect(response.status).to eq(400) + end + + it "should return a 400 error when access level is not given" do + post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id + expect(response.status).to eq(400) + end + + it "should return a 422 error when access level is not known" do + post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234 + expect(response.status).to eq(422) + end + end + end + + describe 'PUT /groups/:id/members/:user_id' do + context 'when not a member of the group' do + it 'should return a 409 error if the user is not a group member' do + put( + api("/groups/#{group_no_members.id}/members/#{developer.id}", + owner), access_level: GroupMember::MASTER + ) + expect(response.status).to eq(404) + end + end + + context 'when a member of the group' do + it 'should return ok and update member access level' do + put( + api("/groups/#{group_with_members.id}/members/#{reporter.id}", + owner), + access_level: GroupMember::MASTER + ) + + expect(response.status).to eq(200) + + get api("/groups/#{group_with_members.id}/members", owner) + json_reporter = json_response.find do |e| + e['id'] == reporter.id + end + + expect(json_reporter['access_level']).to eq(GroupMember::MASTER) + end + + it 'should not allow guest to modify group members' do + put( + api("/groups/#{group_with_members.id}/members/#{developer.id}", + guest), + access_level: GroupMember::MASTER + ) + + expect(response.status).to eq(403) + + get api("/groups/#{group_with_members.id}/members", owner) + json_developer = json_response.find do |e| + e['id'] == developer.id + end + + expect(json_developer['access_level']).to eq(GroupMember::DEVELOPER) + end + + it 'should return a 400 error when access level is not given' do + put( + api("/groups/#{group_with_members.id}/members/#{master.id}", owner) + ) + expect(response.status).to eq(400) + end + + it 'should return a 422 error when access level is not known' do + put( + api("/groups/#{group_with_members.id}/members/#{master.id}", owner), + access_level: 1234 + ) + expect(response.status).to eq(422) + end + end + end + + describe "DELETE /groups/:id/members/:user_id" do + context "when not a member of the group" do + it "should not delete guest's membership of group_with_members" do + random_user = create(:user) + delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user) + expect(response.status).to eq(403) + end + end + + context "when a member of the group" do + it "should delete guest's membership of group" do + expect { + delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner) + }.to change { group_with_members.members.count }.by(-1) + + expect(response.status).to eq(200) + end + + it "should return a 404 error when user id is not known" do + delete api("/groups/#{group_with_members.id}/members/1328", owner) + expect(response.status).to eq(404) + end + + it "should not allow guest to modify group members" do + delete api("/groups/#{group_with_members.id}/members/#{master.id}", guest) + expect(response.status).to eq(403) + end + end + end +end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index 42ccad71aaf..d963dbac9f1 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -18,26 +18,26 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/groups") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when authenticated as user" do it "normal user: should return an array of groups of user1" do get api("/groups", user1) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['name'].should == group1.name + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['name']).to eq(group1.name) end end context "when authenticated as admin" do it "admin: should return an array of all groups" do get api("/groups", admin) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 2 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) end end end @@ -46,31 +46,49 @@ describe API::API, api: true do context "when authenticated as user" do it "should return one of user1's groups" do get api("/groups/#{group1.id}", user1) - response.status.should == 200 + expect(response.status).to eq(200) json_response['name'] == group1.name end it "should not return a non existing group" do get api("/groups/1328", user1) - response.status.should == 404 + expect(response.status).to eq(404) end it "should not return a group not attached to user1" do get api("/groups/#{group2.id}", user1) - response.status.should == 403 + expect(response.status).to eq(403) end end context "when authenticated as admin" do it "should return any existing group" do get api("/groups/#{group2.id}", admin) - response.status.should == 200 + expect(response.status).to eq(200) json_response['name'] == group2.name end it "should not return a non existing group" do get api("/groups/1328", admin) - response.status.should == 404 + expect(response.status).to eq(404) + end + end + + context 'when using group path in URL' do + it 'should return any existing group' do + get api("/groups/#{group1.path}", admin) + expect(response.status).to eq(200) + json_response['name'] == group2.name + end + + it 'should not return a non existing group' do + get api('/groups/unknown', admin) + expect(response.status).to eq(404) + end + + it 'should not return a group not attached to user1' do + get api("/groups/#{group2.path}", user1) + expect(response.status).to eq(403) end end end @@ -79,29 +97,30 @@ describe API::API, api: true do context "when authenticated as user" do it "should not create group" do post api("/groups", user1), attributes_for(:group) - response.status.should == 403 + expect(response.status).to eq(403) end end context "when authenticated as admin" do it "should create group" do post api("/groups", admin), attributes_for(:group) - response.status.should == 201 + expect(response.status).to eq(201) end it "should not create group, duplicate" do post api("/groups", admin), {name: "Duplicate Test", path: group2.path} - response.status.should == 404 + expect(response.status).to eq(400) + expect(response.message).to eq("Bad Request") end it "should return 400 bad request error if name not given" do post api("/groups", admin), {path: group2.path} - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 bad request error if path not given" do post api("/groups", admin), { name: 'test' } - response.status.should == 400 + expect(response.status).to eq(400) end end end @@ -110,36 +129,36 @@ describe API::API, api: true do context "when authenticated as user" do it "should remove group" do delete api("/groups/#{group1.id}", user1) - response.status.should == 200 + expect(response.status).to eq(200) end it "should not remove a group if not an owner" do user3 = create(:user) group1.add_user(user3, Gitlab::Access::MASTER) delete api("/groups/#{group1.id}", user3) - response.status.should == 403 + expect(response.status).to eq(403) end it "should not remove a non existing group" do delete api("/groups/1328", user1) - response.status.should == 404 + expect(response.status).to eq(404) end it "should not remove a group not attached to user1" do delete api("/groups/#{group2.id}", user1) - response.status.should == 403 + expect(response.status).to eq(403) end end context "when authenticated as admin" do it "should remove any existing group" do delete api("/groups/#{group2.id}", admin) - response.status.should == 200 + expect(response.status).to eq(200) end it "should not remove a non existing group" do delete api("/groups/1328", admin) - response.status.should == 404 + expect(response.status).to eq(404) end end end @@ -148,130 +167,20 @@ describe API::API, api: true do let(:project) { create(:project) } before(:each) do Projects::TransferService.any_instance.stub(execute: true) - Project.stub(:find).and_return(project) + allow(Project).to receive(:find).and_return(project) end context "when authenticated as user" do it "should not transfer project to group" do post api("/groups/#{group1.id}/projects/#{project.id}", user2) - response.status.should == 403 + expect(response.status).to eq(403) end end context "when authenticated as admin" do it "should transfer project to group" do post api("/groups/#{group1.id}/projects/#{project.id}", admin) - response.status.should == 201 - end - end - end - - describe "members" do - let(:owner) { create(:user) } - let(:reporter) { create(:user) } - let(:developer) { create(:user) } - let(:master) { create(:user) } - let(:guest) { create(:user) } - let!(:group_with_members) do - group = create(:group) - group.add_users([reporter.id], GroupMember::REPORTER) - group.add_users([developer.id], GroupMember::DEVELOPER) - group.add_users([master.id], GroupMember::MASTER) - group.add_users([guest.id], GroupMember::GUEST) - group - end - let!(:group_no_members) { create(:group) } - - before do - group_with_members.add_owner owner - group_no_members.add_owner owner - end - - describe "GET /groups/:id/members" do - context "when authenticated as user that is part or the group" do - it "each user: should return an array of members groups of group3" do - [owner, master, developer, reporter, guest].each do |user| - get api("/groups/#{group_with_members.id}/members", user) - response.status.should == 200 - json_response.should be_an Array - json_response.size.should == 5 - json_response.find { |e| e['id']==owner.id }['access_level'].should == GroupMember::OWNER - json_response.find { |e| e['id']==reporter.id }['access_level'].should == GroupMember::REPORTER - json_response.find { |e| e['id']==developer.id }['access_level'].should == GroupMember::DEVELOPER - json_response.find { |e| e['id']==master.id }['access_level'].should == GroupMember::MASTER - json_response.find { |e| e['id']==guest.id }['access_level'].should == GroupMember::GUEST - end - end - - it "users not part of the group should get access error" do - get api("/groups/#{group_with_members.id}/members", user1) - response.status.should == 403 - end - end - end - - describe "POST /groups/:id/members" do - context "when not a member of the group" do - it "should not add guest as member of group_no_members when adding being done by person outside the group" do - post api("/groups/#{group_no_members.id}/members", reporter), user_id: guest.id, access_level: GroupMember::MASTER - response.status.should == 403 - end - end - - context "when a member of the group" do - it "should return ok and add new member" do - count_before=group_no_members.group_members.count - new_user = create(:user) - post api("/groups/#{group_no_members.id}/members", owner), user_id: new_user.id, access_level: GroupMember::MASTER - response.status.should == 201 - json_response['name'].should == new_user.name - json_response['access_level'].should == GroupMember::MASTER - group_no_members.group_members.count.should == count_before + 1 - end - - it "should return error if member already exists" do - post api("/groups/#{group_with_members.id}/members", owner), user_id: master.id, access_level: GroupMember::MASTER - response.status.should == 409 - end - - it "should return a 400 error when user id is not given" do - post api("/groups/#{group_no_members.id}/members", owner), access_level: GroupMember::MASTER - response.status.should == 400 - end - - it "should return a 400 error when access level is not given" do - post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id - response.status.should == 400 - end - - it "should return a 422 error when access level is not known" do - post api("/groups/#{group_no_members.id}/members", owner), user_id: master.id, access_level: 1234 - response.status.should == 422 - end - end - end - - describe "DELETE /groups/:id/members/:user_id" do - context "when not a member of the group" do - it "should not delete guest's membership of group_with_members" do - random_user = create(:user) - delete api("/groups/#{group_with_members.id}/members/#{owner.id}", random_user) - response.status.should == 403 - end - end - - context "when a member of the group" do - it "should delete guest's membership of group" do - count_before=group_with_members.group_members.count - delete api("/groups/#{group_with_members.id}/members/#{guest.id}", owner) - response.status.should == 200 - group_with_members.group_members.count.should == count_before - 1 - end - - it "should return a 404 error when user id is not known" do - delete api("/groups/#{group_with_members.id}/members/1328", owner) - response.status.should == 404 - end + expect(response.status).to eq(201) end end end diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb index 6df5ef38961..4c7d15d6594 100644 --- a/spec/requests/api/internal_spec.rb +++ b/spec/requests/api/internal_spec.rb @@ -5,27 +5,50 @@ describe API::API, api: true do let(:user) { create(:user) } let(:key) { create(:key, user: user) } let(:project) { create(:project) } + let(:secret_token) { File.read Rails.root.join('.gitlab_shell_secret') } describe "GET /internal/check", no_db: true do it do - get api("/internal/check") + get api("/internal/check"), secret_token: secret_token - response.status.should == 200 - json_response['api_version'].should == API::API.version + expect(response.status).to eq(200) + expect(json_response['api_version']).to eq(API::API.version) + end + end + + describe "GET /internal/broadcast_message" do + context "broadcast message exists" do + let!(:broadcast_message) { create(:broadcast_message, starts_at: Time.now.yesterday, ends_at: Time.now.tomorrow ) } + + it do + get api("/internal/broadcast_message"), secret_token: secret_token + + expect(response.status).to eq(200) + expect(json_response["message"]).to eq(broadcast_message.message) + end + end + + context "broadcast message doesn't exist" do + it do + get api("/internal/broadcast_message"), secret_token: secret_token + + expect(response.status).to eq(200) + expect(json_response).to be_empty + end end end describe "GET /internal/discover" do it do - get(api("/internal/discover"), key_id: key.id) + get(api("/internal/discover"), key_id: key.id, secret_token: secret_token) - response.status.should == 200 + expect(response.status).to eq(200) - json_response['name'].should == user.name + expect(json_response['name']).to eq(user.name) end end - describe "GET /internal/allowed" do + describe "POST /internal/allowed" do context "access granted" do before do project.team << [user, :developer] @@ -35,8 +58,8 @@ describe API::API, api: true do it do pull(key, project) - response.status.should == 200 - response.body.should == 'true' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_truthy end end @@ -44,8 +67,8 @@ describe API::API, api: true do it do push(key, project) - response.status.should == 200 - response.body.should == 'true' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_truthy end end end @@ -59,8 +82,8 @@ describe API::API, api: true do it do pull(key, project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end @@ -68,8 +91,8 @@ describe API::API, api: true do it do push(key, project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end end @@ -85,8 +108,8 @@ describe API::API, api: true do it do pull(key, personal_project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end @@ -94,8 +117,8 @@ describe API::API, api: true do it do push(key, personal_project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end end @@ -112,8 +135,8 @@ describe API::API, api: true do it do pull(key, project) - response.status.should == 200 - response.body.should == 'true' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_truthy end end @@ -121,8 +144,8 @@ describe API::API, api: true do it do push(key, project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end end @@ -138,8 +161,8 @@ describe API::API, api: true do it do archive(key, project) - response.status.should == 200 - response.body.should == 'true' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_truthy end end @@ -147,11 +170,29 @@ describe API::API, api: true do it do archive(key, project) - response.status.should == 200 - response.body.should == 'false' + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey end end end + + context 'project does not exist' do + it do + pull(key, OpenStruct.new(path_with_namespace: 'gitlab/notexists')) + + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey + end + end + + context 'user does not exist' do + it do + pull(OpenStruct.new(id: 0), project) + + expect(response.status).to eq(200) + expect(json_response["status"]).to be_falsey + end + end end def pull(key, project) @@ -159,7 +200,8 @@ describe API::API, api: true do api("/internal/allowed"), key_id: key.id, project: project.path_with_namespace, - action: 'git-upload-pack' + action: 'git-upload-pack', + secret_token: secret_token ) end @@ -169,7 +211,8 @@ describe API::API, api: true do changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master', key_id: key.id, project: project.path_with_namespace, - action: 'git-receive-pack' + action: 'git-receive-pack', + secret_token: secret_token ) end @@ -179,7 +222,8 @@ describe API::API, api: true do ref: 'master', key_id: key.id, project: project.path_with_namespace, - action: 'git-upload-archive' + action: 'git-upload-archive', + secret_token: secret_token ) end end diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb index 775d7b4e18d..b6b0427debf 100644 --- a/spec/requests/api/issues_spec.rb +++ b/spec/requests/api/issues_spec.rb @@ -34,86 +34,87 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/issues") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when authenticated" do it "should return an array of issues" do get api("/issues", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == issue.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(issue.title) end it "should add pagination headers" do get api("/issues?per_page=3", user) - response.headers['Link'].should == + expect(response.headers['Link']).to eq( '<http://www.example.com/api/v3/issues?page=1&per_page=3>; rel="first", <http://www.example.com/api/v3/issues?page=1&per_page=3>; rel="last"' + ) end it 'should return an array of closed issues' do get api('/issues?state=closed', user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['id'].should == closed_issue.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(closed_issue.id) end it 'should return an array of opened issues' do get api('/issues?state=opened', user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['id'].should == issue.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(issue.id) end it 'should return an array of all issues' do get api('/issues?state=all', user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 2 - json_response.first['id'].should == issue.id - json_response.second['id'].should == closed_issue.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.first['id']).to eq(issue.id) + expect(json_response.second['id']).to eq(closed_issue.id) end it 'should return an array of labeled issues' do get api("/issues?labels=#{label.title}", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['labels'].should == [label.title] + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['labels']).to eq([label.title]) end it 'should return an array of labeled issues when at least one label matches' do get api("/issues?labels=#{label.title},foo,bar", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['labels'].should == [label.title] + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['labels']).to eq([label.title]) end it 'should return an empty array if no issue matches labels' do get api('/issues?labels=foo,bar', user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 0 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) end it 'should return an array of labeled issues matching given state' do get api("/issues?labels=#{label.title}&state=opened", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['labels'].should == [label.title] - json_response.first['state'].should == 'opened' + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['labels']).to eq([label.title]) + expect(json_response.first['state']).to eq('opened') end it 'should return an empty array if no issue matches labels and state filters' do get api("/issues?labels=#{label.title}&state=closed", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 0 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) end end end @@ -124,78 +125,78 @@ describe API::API, api: true do it "should return project issues" do get api("#{base_url}/issues", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == issue.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(issue.title) end it 'should return an array of labeled project issues' do get api("#{base_url}/issues?labels=#{label.title}", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['labels'].should == [label.title] + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['labels']).to eq([label.title]) end it 'should return an array of labeled project issues when at least one label matches' do get api("#{base_url}/issues?labels=#{label.title},foo,bar", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['labels'].should == [label.title] + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['labels']).to eq([label.title]) end it 'should return an empty array if no project issue matches labels' do get api("#{base_url}/issues?labels=foo,bar", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 0 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) end it 'should return an empty array if no issue matches milestone' do get api("#{base_url}/issues?milestone=#{empty_milestone.title}", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 0 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) end it 'should return an empty array if milestone does not exist' do get api("#{base_url}/issues?milestone=foo", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 0 + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(0) end it 'should return an array of issues in given milestone' do get api("#{base_url}/issues?milestone=#{title}", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 2 - json_response.first['id'].should == issue.id - json_response.second['id'].should == closed_issue.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.first['id']).to eq(issue.id) + expect(json_response.second['id']).to eq(closed_issue.id) end it 'should return an array of issues matching state in milestone' do get api("#{base_url}/issues?milestone=#{milestone.title}"\ '&state=closed', user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['id'].should == closed_issue.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['id']).to eq(closed_issue.id) end end describe "GET /projects/:id/issues/:issue_id" do it "should return a project issue by id" do get api("/projects/#{project.id}/issues/#{issue.id}", user) - response.status.should == 200 - json_response['title'].should == issue.title - json_response['iid'].should == issue.iid + expect(response.status).to eq(200) + expect(json_response['title']).to eq(issue.title) + expect(json_response['iid']).to eq(issue.iid) end it "should return 404 if issue id not found" do get api("/projects/#{project.id}/issues/54321", user) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -203,32 +204,32 @@ describe API::API, api: true do it "should create a new project issue" do post api("/projects/#{project.id}/issues", user), title: 'new issue', labels: 'label, label2' - response.status.should == 201 - json_response['title'].should == 'new issue' - json_response['description'].should be_nil - json_response['labels'].should == ['label', 'label2'] + expect(response.status).to eq(201) + expect(json_response['title']).to eq('new issue') + expect(json_response['description']).to be_nil + expect(json_response['labels']).to eq(['label', 'label2']) end it "should return a 400 bad request if title not given" do post api("/projects/#{project.id}/issues", user), labels: 'label, label2' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 on invalid label names' do post api("/projects/#{project.id}/issues", user), title: 'new issue', labels: 'label, ?' - response.status.should == 400 - json_response['message']['labels']['?']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['labels']['?']['title']).to eq(['is invalid']) end it 'should return 400 if title is too long' do post api("/projects/#{project.id}/issues", user), title: 'g' * 256 - response.status.should == 400 - json_response['message']['title'].should == [ + expect(response.status).to eq(400) + expect(json_response['message']['title']).to eq([ 'is too long (maximum is 255 characters)' - ] + ]) end end @@ -236,23 +237,23 @@ describe API::API, api: true do it "should update a project issue" do put api("/projects/#{project.id}/issues/#{issue.id}", user), title: 'updated title' - response.status.should == 200 + expect(response.status).to eq(200) - json_response['title'].should == 'updated title' + expect(json_response['title']).to eq('updated title') end it "should return 404 error if issue id not found" do put api("/projects/#{project.id}/issues/44444", user), title: 'updated title' - response.status.should == 404 + expect(response.status).to eq(404) end it 'should return 400 on invalid label names' do put api("/projects/#{project.id}/issues/#{issue.id}", user), title: 'updated title', labels: 'label, ?' - response.status.should == 400 - json_response['message']['labels']['?']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['labels']['?']['title']).to eq(['is invalid']) end end @@ -263,49 +264,49 @@ describe API::API, api: true do it 'should not update labels if not present' do put api("/projects/#{project.id}/issues/#{issue.id}", user), title: 'updated title' - response.status.should == 200 - json_response['labels'].should == [label.title] + expect(response.status).to eq(200) + expect(json_response['labels']).to eq([label.title]) end it 'should remove all labels' do put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: '' - response.status.should == 200 - json_response['labels'].should == [] + expect(response.status).to eq(200) + expect(json_response['labels']).to eq([]) end it 'should update labels' do put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: 'foo,bar' - response.status.should == 200 - json_response['labels'].should include 'foo' - json_response['labels'].should include 'bar' + expect(response.status).to eq(200) + expect(json_response['labels']).to include 'foo' + expect(json_response['labels']).to include 'bar' end it 'should return 400 on invalid label names' do put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: 'label, ?' - response.status.should == 400 - json_response['message']['labels']['?']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['labels']['?']['title']).to eq(['is invalid']) end it 'should allow special label names' do put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: 'label:foo, label-bar,label_bar,label/bar' - response.status.should == 200 - json_response['labels'].should include 'label:foo' - json_response['labels'].should include 'label-bar' - json_response['labels'].should include 'label_bar' - json_response['labels'].should include 'label/bar' + expect(response.status).to eq(200) + expect(json_response['labels']).to include 'label:foo' + expect(json_response['labels']).to include 'label-bar' + expect(json_response['labels']).to include 'label_bar' + expect(json_response['labels']).to include 'label/bar' end it 'should return 400 if title is too long' do put api("/projects/#{project.id}/issues/#{issue.id}", user), title: 'g' * 256 - response.status.should == 400 - json_response['message']['title'].should == [ + expect(response.status).to eq(400) + expect(json_response['message']['title']).to eq([ 'is too long (maximum is 255 characters)' - ] + ]) end end @@ -313,17 +314,17 @@ describe API::API, api: true do it "should update a project issue" do put api("/projects/#{project.id}/issues/#{issue.id}", user), labels: 'label2', state_event: "close" - response.status.should == 200 + expect(response.status).to eq(200) - json_response['labels'].should include 'label2' - json_response['state'].should eq "closed" + expect(json_response['labels']).to include 'label2' + expect(json_response['state']).to eq "closed" end end describe "DELETE /projects/:id/issues/:issue_id" do it "should delete a project issue" do delete api("/projects/#{project.id}/issues/#{issue.id}", user) - response.status.should == 405 + expect(response.status).to eq(405) end end end diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb index dbddc8a7da4..aff109a9424 100644 --- a/spec/requests/api/labels_spec.rb +++ b/spec/requests/api/labels_spec.rb @@ -15,10 +15,10 @@ describe API::API, api: true do describe 'GET /projects/:id/labels' do it 'should return project labels' do get api("/projects/#{project.id}/labels", user) - response.status.should == 200 - json_response.should be_an Array - json_response.size.should == 1 - json_response.first['name'].should == label1.name + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(1) + expect(json_response.first['name']).to eq(label1.name) end end @@ -27,69 +27,69 @@ describe API::API, api: true do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAABB' - response.status.should == 201 - json_response['name'].should == 'Foo' - json_response['color'].should == '#FFAABB' + expect(response.status).to eq(201) + expect(json_response['name']).to eq('Foo') + expect(json_response['color']).to eq('#FFAABB') end it 'should return a 400 bad request if name not given' do post api("/projects/#{project.id}/labels", user), color: '#FFAABB' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return a 400 bad request if color not given' do post api("/projects/#{project.id}/labels", user), name: 'Foobar' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 for invalid color' do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAA' - response.status.should == 400 - json_response['message']['color'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['color']).to eq(['is invalid']) end it 'should return 400 for too long color code' do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAAFFFF' - response.status.should == 400 - json_response['message']['color'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['color']).to eq(['is invalid']) end it 'should return 400 for invalid name' do post api("/projects/#{project.id}/labels", user), name: '?', color: '#FFAABB' - response.status.should == 400 - json_response['message']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['title']).to eq(['is invalid']) end it 'should return 409 if label already exists' do post api("/projects/#{project.id}/labels", user), name: 'label1', color: '#FFAABB' - response.status.should == 409 - json_response['message'].should == 'Label already exists' + expect(response.status).to eq(409) + expect(json_response['message']).to eq('Label already exists') end end describe 'DELETE /projects/:id/labels' do it 'should return 200 for existing label' do delete api("/projects/#{project.id}/labels", user), name: 'label1' - response.status.should == 200 + expect(response.status).to eq(200) end it 'should return 404 for non existing label' do delete api("/projects/#{project.id}/labels", user), name: 'label2' - response.status.should == 404 - json_response['message'].should == '404 Label Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Label Not Found') end it 'should return 400 for wrong parameters' do delete api("/projects/#{project.id}/labels", user) - response.status.should == 400 + expect(response.status).to eq(400) end end @@ -99,47 +99,47 @@ describe API::API, api: true do name: 'label1', new_name: 'New Label', color: '#FFFFFF' - response.status.should == 200 - json_response['name'].should == 'New Label' - json_response['color'].should == '#FFFFFF' + expect(response.status).to eq(200) + expect(json_response['name']).to eq('New Label') + expect(json_response['color']).to eq('#FFFFFF') end it 'should return 200 if name is changed' do put api("/projects/#{project.id}/labels", user), name: 'label1', new_name: 'New Label' - response.status.should == 200 - json_response['name'].should == 'New Label' - json_response['color'].should == label1.color + expect(response.status).to eq(200) + expect(json_response['name']).to eq('New Label') + expect(json_response['color']).to eq(label1.color) end it 'should return 200 if colors is changed' do put api("/projects/#{project.id}/labels", user), name: 'label1', color: '#FFFFFF' - response.status.should == 200 - json_response['name'].should == label1.name - json_response['color'].should == '#FFFFFF' + expect(response.status).to eq(200) + expect(json_response['name']).to eq(label1.name) + expect(json_response['color']).to eq('#FFFFFF') end it 'should return 404 if label does not exist' do put api("/projects/#{project.id}/labels", user), name: 'label2', new_name: 'label3' - response.status.should == 404 + expect(response.status).to eq(404) end it 'should return 400 if no label name given' do put api("/projects/#{project.id}/labels", user), new_name: 'label2' - response.status.should == 400 - json_response['message'].should == '400 (Bad request) "name" not given' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "name" not given') end it 'should return 400 if no new parameters given' do put api("/projects/#{project.id}/labels", user), name: 'label1' - response.status.should == 400 - json_response['message'].should == 'Required parameters '\ - '"new_name" or "color" missing' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Required parameters '\ + '"new_name" or "color" missing') end it 'should return 400 for invalid name' do @@ -147,24 +147,24 @@ describe API::API, api: true do name: 'label1', new_name: '?', color: '#FFFFFF' - response.status.should == 400 - json_response['message']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['title']).to eq(['is invalid']) end it 'should return 400 for invalid name' do put api("/projects/#{project.id}/labels", user), name: 'label1', color: '#FF' - response.status.should == 400 - json_response['message']['color'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['color']).to eq(['is invalid']) end it 'should return 400 for too long color code' do post api("/projects/#{project.id}/labels", user), name: 'Foo', color: '#FFAAFFFF' - response.status.should == 400 - json_response['message']['color'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['color']).to eq(['is invalid']) end end end diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb index 5ba3a330991..9e252441a4f 100644 --- a/spec/requests/api/merge_requests_spec.rb +++ b/spec/requests/api/merge_requests_spec.rb @@ -16,46 +16,50 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/projects/#{project.id}/merge_requests") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when authenticated" do it "should return an array of all merge_requests" do get api("/projects/#{project.id}/merge_requests", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['title'].should == merge_request.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.last['title']).to eq(merge_request.title) end + it "should return an array of all merge_requests" do get api("/projects/#{project.id}/merge_requests?state", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['title'].should == merge_request.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.last['title']).to eq(merge_request.title) end + it "should return an array of open merge_requests" do get api("/projects/#{project.id}/merge_requests?state=opened", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['title'].should == merge_request.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.last['title']).to eq(merge_request.title) end + it "should return an array of closed merge_requests" do get api("/projects/#{project.id}/merge_requests?state=closed", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 2 - json_response.first['title'].should == merge_request_closed.title - json_response.second['title'].should == merge_request_merged.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(2) + expect(json_response.second['title']).to eq(merge_request_closed.title) + expect(json_response.first['title']).to eq(merge_request_merged.title) end + it "should return an array of merged merge_requests" do get api("/projects/#{project.id}/merge_requests?state=merged", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['title'].should == merge_request_merged.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['title']).to eq(merge_request_merged.title) end context "with ordering" do @@ -66,35 +70,38 @@ describe API::API, api: true do it "should return an array of merge_requests in ascending order" do get api("/projects/#{project.id}/merge_requests?sort=asc", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['id'].should == @mr_earlier.id - json_response.last['id'].should == @mr_later.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.last['id']).to eq(@mr_earlier.id) + expect(json_response.first['id']).to eq(@mr_later.id) end + it "should return an array of merge_requests in descending order" do get api("/projects/#{project.id}/merge_requests?sort=desc", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['id'].should == @mr_later.id - json_response.last['id'].should == @mr_earlier.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.first['id']).to eq(@mr_later.id) + expect(json_response.last['id']).to eq(@mr_earlier.id) end + it "should return an array of merge_requests ordered by updated_at" do get api("/projects/#{project.id}/merge_requests?order_by=updated_at", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['id'].should == @mr_earlier.id - json_response.last['id'].should == @mr_later.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.last['id']).to eq(@mr_earlier.id) + expect(json_response.first['id']).to eq(@mr_later.id) end + it "should return an array of merge_requests ordered by created_at" do get api("/projects/#{project.id}/merge_requests?sort=created_at", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 3 - json_response.first['id'].should == @mr_earlier.id - json_response.last['id'].should == @mr_later.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(3) + expect(json_response.last['id']).to eq(@mr_earlier.id) + expect(json_response.first['id']).to eq(@mr_later.id) end end end @@ -103,14 +110,27 @@ describe API::API, api: true do describe "GET /projects/:id/merge_request/:merge_request_id" do it "should return merge_request" do get api("/projects/#{project.id}/merge_request/#{merge_request.id}", user) - response.status.should == 200 - json_response['title'].should == merge_request.title - json_response['iid'].should == merge_request.iid + expect(response.status).to eq(200) + expect(json_response['title']).to eq(merge_request.title) + expect(json_response['iid']).to eq(merge_request.iid) end it "should return a 404 error if merge_request_id not found" do get api("/projects/#{project.id}/merge_request/999", user) - response.status.should == 404 + expect(response.status).to eq(404) + end + end + + describe 'GET /projects/:id/merge_request/:merge_request_id/changes' do + it 'should return the change information of the merge_request' do + get api("/projects/#{project.id}/merge_request/#{merge_request.id}/changes", user) + expect(response.status).to eq 200 + expect(json_response['changes'].size).to eq(merge_request.diffs.size) + end + + it 'returns a 404 when merge_request_id not found' do + get api("/projects/#{project.id}/merge_request/999/changes", user) + expect(response.status).to eq(404) end end @@ -123,33 +143,33 @@ describe API::API, api: true do target_branch: 'master', author: user, labels: 'label, label2' - response.status.should == 201 - json_response['title'].should == 'Test merge_request' - json_response['labels'].should == ['label', 'label2'] + expect(response.status).to eq(201) + expect(json_response['title']).to eq('Test merge_request') + expect(json_response['labels']).to eq(['label', 'label2']) end it "should return 422 when source_branch equals target_branch" do post api("/projects/#{project.id}/merge_requests", user), title: "Test merge_request", source_branch: "master", target_branch: "master", author: user - response.status.should == 422 + expect(response.status).to eq(422) end it "should return 400 when source_branch is missing" do post api("/projects/#{project.id}/merge_requests", user), title: "Test merge_request", target_branch: "master", author: user - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 when target_branch is missing" do post api("/projects/#{project.id}/merge_requests", user), title: "Test merge_request", source_branch: "stable", author: user - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 when title is missing" do post api("/projects/#{project.id}/merge_requests", user), target_branch: 'master', source_branch: 'stable' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 on invalid label names' do @@ -159,9 +179,10 @@ describe API::API, api: true do target_branch: 'master', author: user, labels: 'label, ?' - response.status.should == 400 - json_response['message']['labels']['?']['title'].should == + expect(response.status).to eq(400) + expect(json_response['message']['labels']['?']['title']).to eq( ['is invalid'] + ) end context 'with existing MR' do @@ -182,7 +203,7 @@ describe API::API, api: true do target_branch: 'master', author: user end.to change { MergeRequest.count }.by(0) - response.status.should == 409 + expect(response.status).to eq(409) end end end @@ -199,37 +220,37 @@ describe API::API, api: true do it "should return merge_request" do post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', source_branch: "stable", target_branch: "master", author: user2, target_project_id: project.id, description: 'Test description for Test merge_request' - response.status.should == 201 - json_response['title'].should == 'Test merge_request' - json_response['description'].should == 'Test description for Test merge_request' + expect(response.status).to eq(201) + expect(json_response['title']).to eq('Test merge_request') + expect(json_response['description']).to eq('Test description for Test merge_request') end it "should not return 422 when source_branch equals target_branch" do - project.id.should_not == fork_project.id - fork_project.forked?.should be_true - fork_project.forked_from_project.should == project + expect(project.id).not_to eq(fork_project.id) + expect(fork_project.forked?).to be_truthy + expect(fork_project.forked_from_project).to eq(project) post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', source_branch: "master", target_branch: "master", author: user2, target_project_id: project.id - response.status.should == 201 - json_response['title'].should == 'Test merge_request' + expect(response.status).to eq(201) + expect(json_response['title']).to eq('Test merge_request') end it "should return 400 when source_branch is missing" do post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 when target_branch is missing" do post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', target_branch: "master", author: user2, target_project_id: project.id - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 when title is missing" do post api("/projects/#{fork_project.id}/merge_requests", user2), target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: project.id - response.status.should == 400 + expect(response.status).to eq(400) end context 'when target_branch is specified' do @@ -240,7 +261,7 @@ describe API::API, api: true do source_branch: 'stable', author: user, target_project_id: fork_project.id - response.status.should == 422 + expect(response.status).to eq(422) end it 'should return 422 if targeting a different fork' do @@ -250,14 +271,14 @@ describe API::API, api: true do source_branch: 'stable', author: user2, target_project_id: unrelated_project.id - response.status.should == 422 + expect(response.status).to eq(422) end end it "should return 201 when target_branch is specified and for the same project" do post api("/projects/#{fork_project.id}/merge_requests", user2), title: 'Test merge_request', target_branch: 'master', source_branch: 'stable', author: user2, target_project_id: fork_project.id - response.status.should == 201 + expect(response.status).to eq(201) end end end @@ -265,8 +286,8 @@ describe API::API, api: true do describe "PUT /projects/:id/merge_request/:merge_request_id to close MR" do it "should return merge_request" do put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), state_event: "close" - response.status.should == 200 - json_response['state'].should == 'closed' + expect(response.status).to eq(200) + expect(json_response['state']).to eq('closed') end end @@ -274,55 +295,55 @@ describe API::API, api: true do it "should return merge_request in case of success" do MergeRequest.any_instance.stub(can_be_merged?: true, automerge!: true) put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return 405 if branch can't be merged" do MergeRequest.any_instance.stub(can_be_merged?: false) put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) - response.status.should == 405 - json_response['message'].should == 'Branch cannot be merged' + expect(response.status).to eq(405) + expect(json_response['message']).to eq('Branch cannot be merged') end it "should return 405 if merge_request is not open" do merge_request.close put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user) - response.status.should == 405 - json_response['message'].should == '405 Method Not Allowed' + expect(response.status).to eq(405) + expect(json_response['message']).to eq('405 Method Not Allowed') end it "should return 401 if user has no permissions to merge" do user2 = create(:user) project.team << [user2, :reporter] put api("/projects/#{project.id}/merge_request/#{merge_request.id}/merge", user2) - response.status.should == 401 - json_response['message'].should == '401 Unauthorized' + expect(response.status).to eq(401) + expect(json_response['message']).to eq('401 Unauthorized') end end describe "PUT /projects/:id/merge_request/:merge_request_id" do it "should return merge_request" do put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), title: "New title" - response.status.should == 200 - json_response['title'].should == 'New title' + expect(response.status).to eq(200) + expect(json_response['title']).to eq('New title') end it "should return merge_request" do put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), description: "New description" - response.status.should == 200 - json_response['description'].should == 'New description' + expect(response.status).to eq(200) + expect(json_response['description']).to eq('New description') end it "should return 422 when source_branch and target_branch are renamed the same" do put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), source_branch: "master", target_branch: "master" - response.status.should == 422 + expect(response.status).to eq(422) end it "should return merge_request with renamed target_branch" do put api("/projects/#{project.id}/merge_request/#{merge_request.id}", user), target_branch: "wiki" - response.status.should == 200 - json_response['target_branch'].should == 'wiki' + expect(response.status).to eq(200) + expect(json_response['target_branch']).to eq('wiki') end it 'should return 400 on invalid label names' do @@ -330,43 +351,43 @@ describe API::API, api: true do user), title: 'new issue', labels: 'label, ?' - response.status.should == 400 - json_response['message']['labels']['?']['title'].should == ['is invalid'] + expect(response.status).to eq(400) + expect(json_response['message']['labels']['?']['title']).to eq(['is invalid']) end end describe "POST /projects/:id/merge_request/:merge_request_id/comments" do it "should return comment" do post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user), note: "My comment" - response.status.should == 201 - json_response['note'].should == 'My comment' + expect(response.status).to eq(201) + expect(json_response['note']).to eq('My comment') end it "should return 400 if note is missing" do post api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 404 if note is attached to non existent merge request" do post api("/projects/#{project.id}/merge_request/404/comments", user), note: 'My comment' - response.status.should == 404 + expect(response.status).to eq(404) end end describe "GET :id/merge_request/:merge_request_id/comments" do it "should return merge_request comments" do get api("/projects/#{project.id}/merge_request/#{merge_request.id}/comments", user) - response.status.should == 200 - json_response.should be_an Array - json_response.length.should == 1 - json_response.first['note'].should == "a comment on a MR" - json_response.first['author']['id'].should == user.id + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + expect(json_response.first['note']).to eq("a comment on a MR") + expect(json_response.first['author']['id']).to eq(user.id) end it "should return a 404 error if merge_request_id not found" do get api("/projects/#{project.id}/merge_request/999/comments", user) - response.status.should == 404 + expect(response.status).to eq(404) end end diff --git a/spec/requests/api/milestones_spec.rb b/spec/requests/api/milestones_spec.rb index f0619a1c801..effb0723476 100644 --- a/spec/requests/api/milestones_spec.rb +++ b/spec/requests/api/milestones_spec.rb @@ -8,92 +8,109 @@ describe API::API, api: true do before { project.team << [user, :developer] } - describe "GET /projects/:id/milestones" do - it "should return project milestones" do + describe 'GET /projects/:id/milestones' do + it 'should return project milestones' do get api("/projects/#{project.id}/milestones", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == milestone.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(milestone.title) end - it "should return a 401 error if user not authenticated" do + it 'should return a 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones") - response.status.should == 401 + expect(response.status).to eq(401) end end - describe "GET /projects/:id/milestones/:milestone_id" do - it "should return a project milestone by id" do + describe 'GET /projects/:id/milestones/:milestone_id' do + it 'should return a project milestone by id' do get api("/projects/#{project.id}/milestones/#{milestone.id}", user) - response.status.should == 200 - json_response['title'].should == milestone.title - json_response['iid'].should == milestone.iid + expect(response.status).to eq(200) + expect(json_response['title']).to eq(milestone.title) + expect(json_response['iid']).to eq(milestone.iid) end - it "should return 401 error if user not authenticated" do + it 'should return 401 error if user not authenticated' do get api("/projects/#{project.id}/milestones/#{milestone.id}") - response.status.should == 401 + expect(response.status).to eq(401) end - it "should return a 404 error if milestone id not found" do + it 'should return a 404 error if milestone id not found' do get api("/projects/#{project.id}/milestones/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "POST /projects/:id/milestones" do - it "should create a new project milestone" do + describe 'POST /projects/:id/milestones' do + it 'should create a new project milestone' do post api("/projects/#{project.id}/milestones", user), title: 'new milestone' - response.status.should == 201 - json_response['title'].should == 'new milestone' - json_response['description'].should be_nil + expect(response.status).to eq(201) + expect(json_response['title']).to eq('new milestone') + expect(json_response['description']).to be_nil end - it "should create a new project milestone with description and due date" do + it 'should create a new project milestone with description and due date' do post api("/projects/#{project.id}/milestones", user), title: 'new milestone', description: 'release', due_date: '2013-03-02' - response.status.should == 201 - json_response['description'].should == 'release' - json_response['due_date'].should == '2013-03-02' + expect(response.status).to eq(201) + expect(json_response['description']).to eq('release') + expect(json_response['due_date']).to eq('2013-03-02') end - it "should return a 400 error if title is missing" do + it 'should return a 400 error if title is missing' do post api("/projects/#{project.id}/milestones", user) - response.status.should == 400 + expect(response.status).to eq(400) end end - describe "PUT /projects/:id/milestones/:milestone_id" do - it "should update a project milestone" do + describe 'PUT /projects/:id/milestones/:milestone_id' do + it 'should update a project milestone' do put api("/projects/#{project.id}/milestones/#{milestone.id}", user), title: 'updated title' - response.status.should == 200 - json_response['title'].should == 'updated title' + expect(response.status).to eq(200) + expect(json_response['title']).to eq('updated title') end - it "should return a 404 error if milestone id not found" do + it 'should return a 404 error if milestone id not found' do put api("/projects/#{project.id}/milestones/1234", user), title: 'updated title' - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "PUT /projects/:id/milestones/:milestone_id to close milestone" do - it "should update a project milestone" do + describe 'PUT /projects/:id/milestones/:milestone_id to close milestone' do + it 'should update a project milestone' do put api("/projects/#{project.id}/milestones/#{milestone.id}", user), state_event: 'close' - response.status.should == 200 + expect(response.status).to eq(200) - json_response['state'].should == 'closed' + expect(json_response['state']).to eq('closed') end end - describe "PUT /projects/:id/milestones/:milestone_id to test observer on close" do - it "should create an activity event when an milestone is closed" do - Event.should_receive(:create) + describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do + it 'should create an activity event when an milestone is closed' do + expect(Event).to receive(:create) put api("/projects/#{project.id}/milestones/#{milestone.id}", user), state_event: 'close' end end + + describe 'GET /projects/:id/milestones/:milestone_id/issues' do + before do + milestone.issues << create(:issue) + end + it 'should return project issues for a particular milestone' do + get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['milestone']['title']).to eq(milestone.title) + end + + it 'should return a 401 error if user not authenticated' do + get api("/projects/#{project.id}/milestones/#{milestone.id}/issues") + expect(response.status).to eq(401) + end + end end diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb index b8943ea0762..6ddaaa0a6dd 100644 --- a/spec/requests/api/namespaces_spec.rb +++ b/spec/requests/api/namespaces_spec.rb @@ -10,17 +10,17 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/namespaces") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when authenticated as admin" do it "admin: should return an array of all namespaces" do get api("/namespaces", admin) - response.status.should == 200 - json_response.should be_an Array + expect(response.status).to eq(200) + expect(json_response).to be_an Array - json_response.length.should == Namespace.count + expect(json_response.length).to eq(Namespace.count) end end end diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb index 7aa53787aed..8b177af4689 100644 --- a/spec/requests/api/notes_spec.rb +++ b/spec/requests/api/notes_spec.rb @@ -16,42 +16,42 @@ describe API::API, api: true do context "when noteable is an Issue" do it "should return an array of issue notes" do get api("/projects/#{project.id}/issues/#{issue.id}/notes", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['body'].should == issue_note.note + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['body']).to eq(issue_note.note) end it "should return a 404 error when issue id not found" do get api("/projects/#{project.id}/issues/123/notes", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "when noteable is a Snippet" do it "should return an array of snippet notes" do get api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['body'].should == snippet_note.note + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['body']).to eq(snippet_note.note) end it "should return a 404 error when snippet id not found" do get api("/projects/#{project.id}/snippets/42/notes", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "when noteable is a Merge Request" do it "should return an array of merge_requests notes" do get api("/projects/#{project.id}/merge_requests/#{merge_request.id}/notes", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['body'].should == merge_request_note.note + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['body']).to eq(merge_request_note.note) end it "should return a 404 error if merge request id not found" do get api("/projects/#{project.id}/merge_requests/4444/notes", user) - response.status.should == 404 + expect(response.status).to eq(404) end end end @@ -60,26 +60,26 @@ describe API::API, api: true do context "when noteable is an Issue" do it "should return an issue note by id" do get api("/projects/#{project.id}/issues/#{issue.id}/notes/#{issue_note.id}", user) - response.status.should == 200 - json_response['body'].should == issue_note.note + expect(response.status).to eq(200) + expect(json_response['body']).to eq(issue_note.note) end it "should return a 404 error if issue note not found" do get api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "when noteable is a Snippet" do it "should return a snippet note by id" do get api("/projects/#{project.id}/snippets/#{snippet.id}/notes/#{snippet_note.id}", user) - response.status.should == 200 - json_response['body'].should == snippet_note.note + expect(response.status).to eq(200) + expect(json_response['body']).to eq(snippet_note.note) end it "should return a 404 error if snippet note not found" do get api("/projects/#{project.id}/snippets/#{snippet.id}/notes/123", user) - response.status.should == 404 + expect(response.status).to eq(404) end end end @@ -88,47 +88,101 @@ describe API::API, api: true do context "when noteable is an Issue" do it "should create a new issue note" do post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!' - response.status.should == 201 - json_response['body'].should == 'hi!' - json_response['author']['username'].should == user.username + expect(response.status).to eq(201) + expect(json_response['body']).to eq('hi!') + expect(json_response['author']['username']).to eq(user.username) end it "should return a 400 bad request error if body not given" do post api("/projects/#{project.id}/issues/#{issue.id}/notes", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 401 unauthorized error if user not authenticated" do post api("/projects/#{project.id}/issues/#{issue.id}/notes"), body: 'hi!' - response.status.should == 401 + expect(response.status).to eq(401) end end context "when noteable is a Snippet" do it "should create a new snippet note" do post api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user), body: 'hi!' - response.status.should == 201 - json_response['body'].should == 'hi!' - json_response['author']['username'].should == user.username + expect(response.status).to eq(201) + expect(json_response['body']).to eq('hi!') + expect(json_response['author']['username']).to eq(user.username) end it "should return a 400 bad request error if body not given" do post api("/projects/#{project.id}/snippets/#{snippet.id}/notes", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 401 unauthorized error if user not authenticated" do post api("/projects/#{project.id}/snippets/#{snippet.id}/notes"), body: 'hi!' - response.status.should == 401 + expect(response.status).to eq(401) end end end describe "POST /projects/:id/noteable/:noteable_id/notes to test observer on create" do it "should create an activity event when an issue note is created" do - Event.should_receive(:create) + expect(Event).to receive(:create) post api("/projects/#{project.id}/issues/#{issue.id}/notes", user), body: 'hi!' end end + + describe 'PUT /projects/:id/noteable/:noteable_id/notes/:note_id' do + context 'when noteable is an Issue' do + it 'should return modified note' do + put api("/projects/#{project.id}/issues/#{issue.id}/"\ + "notes/#{issue_note.id}", user), body: 'Hello!' + expect(response.status).to eq(200) + expect(json_response['body']).to eq('Hello!') + end + + it 'should return a 404 error when note id not found' do + put api("/projects/#{project.id}/issues/#{issue.id}/notes/123", user), + body: 'Hello!' + expect(response.status).to eq(404) + end + + it 'should return a 400 bad request error if body not given' do + put api("/projects/#{project.id}/issues/#{issue.id}/"\ + "notes/#{issue_note.id}", user) + expect(response.status).to eq(400) + end + end + + context 'when noteable is a Snippet' do + it 'should return modified note' do + put api("/projects/#{project.id}/snippets/#{snippet.id}/"\ + "notes/#{snippet_note.id}", user), body: 'Hello!' + expect(response.status).to eq(200) + expect(json_response['body']).to eq('Hello!') + end + + it 'should return a 404 error when note id not found' do + put api("/projects/#{project.id}/snippets/#{snippet.id}/"\ + "notes/123", user), body: "Hello!" + expect(response.status).to eq(404) + end + end + + context 'when noteable is a Merge Request' do + it 'should return modified note' do + put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\ + "notes/#{merge_request_note.id}", user), body: 'Hello!' + expect(response.status).to eq(200) + expect(json_response['body']).to eq('Hello!') + end + + it 'should return a 404 error when note id not found' do + put api("/projects/#{project.id}/merge_requests/#{merge_request.id}/"\ + "notes/123", user), body: "Hello!" + expect(response.status).to eq(404) + end + end + end + end diff --git a/spec/requests/api/project_hooks_spec.rb b/spec/requests/api/project_hooks_spec.rb index cdb5e3d0612..81fe68de662 100644 --- a/spec/requests/api/project_hooks_spec.rb +++ b/spec/requests/api/project_hooks_spec.rb @@ -16,18 +16,18 @@ describe API::API, 'ProjectHooks', api: true do context "authorized user" do it "should return project hooks" do get api("/projects/#{project.id}/hooks", user) - response.status.should == 200 + expect(response.status).to eq(200) - json_response.should be_an Array - json_response.count.should == 1 - json_response.first['url'].should == "http://example.com" + expect(json_response).to be_an Array + expect(json_response.count).to eq(1) + expect(json_response.first['url']).to eq("http://example.com") end end context "unauthorized user" do it "should not access project hooks" do get api("/projects/#{project.id}/hooks", user3) - response.status.should == 403 + expect(response.status).to eq(403) end end end @@ -36,26 +36,26 @@ describe API::API, 'ProjectHooks', api: true do context "authorized user" do it "should return a project hook" do get api("/projects/#{project.id}/hooks/#{hook.id}", user) - response.status.should == 200 - json_response['url'].should == hook.url + expect(response.status).to eq(200) + expect(json_response['url']).to eq(hook.url) end it "should return a 404 error if hook id is not available" do get api("/projects/#{project.id}/hooks/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end context "unauthorized user" do it "should not access an existing hook" do get api("/projects/#{project.id}/hooks/#{hook.id}", user3) - response.status.should == 403 + expect(response.status).to eq(403) end end it "should return a 404 error if hook id is not available" do get api("/projects/#{project.id}/hooks/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -65,17 +65,17 @@ describe API::API, 'ProjectHooks', api: true do post api("/projects/#{project.id}/hooks", user), url: "http://example.com", issues_events: true }.to change {project.hooks.count}.by(1) - response.status.should == 201 + expect(response.status).to eq(201) end it "should return a 400 error if url not given" do post api("/projects/#{project.id}/hooks", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 422 error if url not valid" do post api("/projects/#{project.id}/hooks", user), "url" => "ftp://example.com" - response.status.should == 422 + expect(response.status).to eq(422) end end @@ -83,23 +83,23 @@ describe API::API, 'ProjectHooks', api: true do it "should update an existing project hook" do put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'http://example.org', push_events: false - response.status.should == 200 - json_response['url'].should == 'http://example.org' + expect(response.status).to eq(200) + expect(json_response['url']).to eq('http://example.org') end it "should return 404 error if hook id not found" do put api("/projects/#{project.id}/hooks/1234", user), url: 'http://example.org' - response.status.should == 404 + expect(response.status).to eq(404) end it "should return 400 error if url is not given" do put api("/projects/#{project.id}/hooks/#{hook.id}", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 422 error if url is not valid" do put api("/projects/#{project.id}/hooks/#{hook.id}", user), url: 'ftp://example.com' - response.status.should == 422 + expect(response.status).to eq(422) end end @@ -108,22 +108,22 @@ describe API::API, 'ProjectHooks', api: true do expect { delete api("/projects/#{project.id}/hooks/#{hook.id}", user) }.to change {project.hooks.count}.by(-1) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return success when deleting hook" do delete api("/projects/#{project.id}/hooks/#{hook.id}", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return success when deleting non existent hook" do delete api("/projects/#{project.id}/hooks/42", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return a 405 error if hook id not given" do delete api("/projects/#{project.id}/hooks", user) - response.status.should == 405 + expect(response.status).to eq(405) end end end diff --git a/spec/requests/api/project_members_spec.rb b/spec/requests/api/project_members_spec.rb index 836f21f3e0b..8419a364ed1 100644 --- a/spec/requests/api/project_members_spec.rb +++ b/spec/requests/api/project_members_spec.rb @@ -15,23 +15,23 @@ describe API::API, api: true do it "should return project team members" do get api("/projects/#{project.id}/members", user) - response.status.should == 200 - json_response.should be_an Array - json_response.count.should == 2 - json_response.map { |u| u['username'] }.should include user.username + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.count).to eq(2) + expect(json_response.map { |u| u['username'] }).to include user.username end it "finds team members with query string" do get api("/projects/#{project.id}/members", user), query: user.username - response.status.should == 200 - json_response.should be_an Array - json_response.count.should == 1 - json_response.first['username'].should == user.username + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.count).to eq(1) + expect(json_response.first['username']).to eq(user.username) end it "should return a 404 error if id not found" do get api("/projects/9999/members", user) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -40,14 +40,14 @@ describe API::API, api: true do it "should return project team member" do get api("/projects/#{project.id}/members/#{user.id}", user) - response.status.should == 200 - json_response['username'].should == user.username - json_response['access_level'].should == ProjectMember::MASTER + expect(response.status).to eq(200) + expect(json_response['username']).to eq(user.username) + expect(json_response['access_level']).to eq(ProjectMember::MASTER) end it "should return a 404 error if user id not found" do get api("/projects/#{project.id}/members/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -58,9 +58,9 @@ describe API::API, api: true do access_level: ProjectMember::DEVELOPER }.to change { ProjectMember.count }.by(1) - response.status.should == 201 - json_response['username'].should == user2.username - json_response['access_level'].should == ProjectMember::DEVELOPER + expect(response.status).to eq(201) + expect(json_response['username']).to eq(user2.username) + expect(json_response['access_level']).to eq(ProjectMember::DEVELOPER) end it "should return a 201 status if user is already project member" do @@ -69,26 +69,26 @@ describe API::API, api: true do expect { post api("/projects/#{project.id}/members", user), user_id: user2.id, access_level: ProjectMember::DEVELOPER - }.not_to change { ProjectMember.count }.by(1) + }.not_to change { ProjectMember.count } - response.status.should == 201 - json_response['username'].should == user2.username - json_response['access_level'].should == ProjectMember::DEVELOPER + expect(response.status).to eq(201) + expect(json_response['username']).to eq(user2.username) + expect(json_response['access_level']).to eq(ProjectMember::DEVELOPER) end it "should return a 400 error when user id is not given" do post api("/projects/#{project.id}/members", user), access_level: ProjectMember::MASTER - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 400 error when access level is not given" do post api("/projects/#{project.id}/members", user), user_id: user2.id - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 422 error when access level is not known" do post api("/projects/#{project.id}/members", user), user_id: user2.id, access_level: 1234 - response.status.should == 422 + expect(response.status).to eq(422) end end @@ -97,24 +97,24 @@ describe API::API, api: true do it "should update project team member" do put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: ProjectMember::MASTER - response.status.should == 200 - json_response['username'].should == user3.username - json_response['access_level'].should == ProjectMember::MASTER + expect(response.status).to eq(200) + expect(json_response['username']).to eq(user3.username) + expect(json_response['access_level']).to eq(ProjectMember::MASTER) end it "should return a 404 error if user_id is not found" do put api("/projects/#{project.id}/members/1234", user), access_level: ProjectMember::MASTER - response.status.should == 404 + expect(response.status).to eq(404) end it "should return a 400 error when access level is not given" do put api("/projects/#{project.id}/members/#{user3.id}", user) - response.status.should == 400 + expect(response.status).to eq(400) end it "should return a 422 error when access level is not known" do put api("/projects/#{project.id}/members/#{user3.id}", user), access_level: 123 - response.status.should == 422 + expect(response.status).to eq(422) end end @@ -132,22 +132,22 @@ describe API::API, api: true do delete api("/projects/#{project.id}/members/#{user3.id}", user) expect { delete api("/projects/#{project.id}/members/#{user3.id}", user) - }.to_not change { ProjectMember.count }.by(1) + }.to_not change { ProjectMember.count } end it "should return 200 if team member already removed" do delete api("/projects/#{project.id}/members/#{user3.id}", user) delete api("/projects/#{project.id}/members/#{user3.id}", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return 200 OK when the user was not member" do expect { delete api("/projects/#{project.id}/members/1000000", user) }.to change { ProjectMember.count }.by(0) - response.status.should == 200 - json_response['message'].should == "Access revoked" - json_response['id'].should == 1000000 + expect(response.status).to eq(200) + expect(json_response['message']).to eq("Access revoked") + expect(json_response['id']).to eq(1000000) end end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index aa1437c71aa..f28dfea3ccf 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1,122 +1,149 @@ +# -*- coding: utf-8 -*- require 'spec_helper' describe API::API, api: true do include ApiHelpers + include Gitlab::CurrentSettings let(:user) { create(:user) } let(:user2) { create(:user) } let(:user3) { create(:user) } let(:admin) { create(:admin) } let(:project) { create(:project, creator_id: user.id, namespace: user.namespace) } + let(:project2) { create(:project, path: 'project2', creator_id: user.id, namespace: user.namespace) } + let(:project3) { create(:project, path: 'project3', creator_id: user.id, namespace: user.namespace) } let(:snippet) { create(:project_snippet, author: user, project: project, title: 'example') } let(:project_member) { create(:project_member, user: user, project: project, access_level: ProjectMember::MASTER) } let(:project_member2) { create(:project_member, user: user3, project: project, access_level: ProjectMember::DEVELOPER) } + let(:user4) { create(:user) } + let(:project3) do + create(:project, + name: 'second_project', + path: 'second_project', + creator_id: user.id, + namespace: user.namespace, + merge_requests_enabled: false, + issues_enabled: false, wiki_enabled: false, + snippets_enabled: false, visibility_level: 0) + end + let(:project_member3) do + create(:project_member, + user: user4, + project: project3, + access_level: ProjectMember::MASTER) + end + let(:project4) do + create(:project, + name: 'third_project', + path: 'third_project', + creator_id: user4.id, + namespace: user4.namespace) + end - describe "GET /projects" do + describe 'GET /projects' do before { project } - context "when unauthenticated" do - it "should return authentication error" do - get api("/projects") - response.status.should == 401 + context 'when unauthenticated' do + it 'should return authentication error' do + get api('/projects') + expect(response.status).to eq(401) end end - context "when authenticated" do - it "should return an array of projects" do - get api("/projects", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['name'].should == project.name - json_response.first['owner']['username'].should == user.username + context 'when authenticated' do + it 'should return an array of projects' do + get api('/projects', user) + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(project.name) + expect(json_response.first['owner']['username']).to eq(user.username) + end + + context 'and using search' do + it 'should return searched project' do + get api('/projects', user), { search: project.name } + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.length).to eq(1) + end + end + + context 'and using sorting' do + before do + project2 + project3 + end + + it 'should return the correct order when sorted by id' do + get api('/projects', user), { order_by: 'id', sort: 'desc'} + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['id']).to eq(project3.id) + end end end end - describe "GET /projects/all" do + describe 'GET /projects/all' do before { project } - context "when unauthenticated" do - it "should return authentication error" do - get api("/projects/all") - response.status.should == 401 + context 'when unauthenticated' do + it 'should return authentication error' do + get api('/projects/all') + expect(response.status).to eq(401) end end - context "when authenticated as regular user" do - it "should return authentication error" do - get api("/projects/all", user) - response.status.should == 403 + context 'when authenticated as regular user' do + it 'should return authentication error' do + get api('/projects/all', user) + expect(response.status).to eq(403) end end - context "when authenticated as admin" do - it "should return an array of all projects" do - get api("/projects/all", admin) - response.status.should == 200 - json_response.should be_an Array + context 'when authenticated as admin' do + it 'should return an array of all projects' do + get api('/projects/all', admin) + expect(response.status).to eq(200) + expect(json_response).to be_an Array project_name = project.name - json_response.detect { + expect(json_response.detect { |project| project['name'] == project_name - }['name'].should == project_name + }['name']).to eq(project_name) - json_response.detect { + expect(json_response.detect { |project| project['owner']['username'] == user.username - }['owner']['username'].should == user.username + }['owner']['username']).to eq(user.username) end end end - describe "POST /projects" do - context "maximum number of projects reached" do - before do - (1..user2.projects_limit).each do |project| - post api("/projects", user2), name: "foo#{project}" - end - end - - it "should not create new project" do + describe 'POST /projects' do + context 'maximum number of projects reached' do + it 'should not create new project and respond with 403' do + allow_any_instance_of(User).to receive(:projects_limit_left).and_return(0) expect { - post api("/projects", user2), name: 'foo' + post api('/projects', user2), name: 'foo' }.to change {Project.count}.by(0) + expect(response.status).to eq(403) end end - it "should create new project without path" do - expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1) - end - - it "should not create new project without name" do - expect { post api("/projects", user) }.to_not change {Project.count} - end - - it "should return a 400 error if name not given" do - post api("/projects", user) - response.status.should == 400 - end - - it "should create last project before reaching project limit" do - (1..user2.projects_limit-1).each { |p| post api("/projects", user2), name: "foo#{p}" } - post api("/projects", user2), name: "foo" - response.status.should == 201 - end - - it "should respond with 201 on success" do - post api("/projects", user), name: 'foo' - response.status.should == 201 + it 'should create new project without path and return 201' do + expect { post api('/projects', user), name: 'foo' }. + to change { Project.count }.by(1) + expect(response.status).to eq(201) end - it "should respond with 400 if name is not given" do - post api("/projects", user) - response.status.should == 400 + it 'should create last project before reaching project limit' do + allow_any_instance_of(User).to receive(:projects_limit_left).and_return(1) + post api('/projects', user2), name: 'foo' + expect(response.status).to eq(201) end - it "should return a 403 error if project limit reached" do - (1..user.projects_limit).each do |p| - post api("/projects", user), name: "foo#{p}" - end - post api("/projects", user), name: 'bar' - response.status.should == 403 + it 'should not create new project without name and return 400' do + expect { post api('/projects', user) }.to_not change { Project.count } + expect(response.status).to eq(400) end it "should assign attributes to project" do @@ -128,94 +155,108 @@ describe API::API, api: true do wiki_enabled: false }) - post api("/projects", user), project + post api('/projects', user), project project.each_pair do |k,v| - json_response[k.to_s].should == v + expect(json_response[k.to_s]).to eq(v) end end - it "should set a project as public" do + it 'should set a project as public' do project = attributes_for(:project, :public) - post api("/projects", user), project - json_response['public'].should be_true - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC + post api('/projects', user), project + expect(json_response['public']).to be_truthy + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC) end - it "should set a project as public using :public" do + it 'should set a project as public using :public' do project = attributes_for(:project, { public: true }) - post api("/projects", user), project - json_response['public'].should be_true - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC + post api('/projects', user), project + expect(json_response['public']).to be_truthy + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC) end - it "should set a project as internal" do + it 'should set a project as internal' do project = attributes_for(:project, :internal) - post api("/projects", user), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL + post api('/projects', user), project + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL) end - it "should set a project as internal overriding :public" do + it 'should set a project as internal overriding :public' do project = attributes_for(:project, :internal, { public: true }) - post api("/projects", user), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL + post api('/projects', user), project + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL) end - it "should set a project as private" do + it 'should set a project as private' do project = attributes_for(:project, :private) - post api("/projects", user), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE + post api('/projects', user), project + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE) end - it "should set a project as private using :public" do + it 'should set a project as private using :public' do project = attributes_for(:project, { public: false }) - post api("/projects", user), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE + post api('/projects', user), project + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE) + end + + context 'when a visibility level is restricted' do + before do + @project = attributes_for(:project, { public: true }) + allow_any_instance_of(ApplicationSetting).to( + receive(:restricted_visibility_levels).and_return([20]) + ) + end + + it 'should not allow a non-admin to use a restricted visibility level' do + post api('/projects', user), @project + expect(response.status).to eq(400) + expect(json_response['message']['visibility_level'].first).to( + match('restricted by your GitLab administrator') + ) + end + + it 'should allow an admin to override restricted visibility settings' do + post api('/projects', admin), @project + expect(json_response['public']).to be_truthy + expect(json_response['visibility_level']).to( + eq(Gitlab::VisibilityLevel::PUBLIC) + ) + end end end - describe "POST /projects/user/:id" do + describe 'POST /projects/user/:id' do before { project } before { admin } - it "should create new project without path" do + it 'should create new project without path and return 201' do expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1) + expect(response.status).to eq(201) end - it "should not create new project without name" do - expect { post api("/projects/user/#{user.id}", admin) }.to_not change {Project.count} - end + it 'should respond with 400 on failure and not project' do + expect { post api("/projects/user/#{user.id}", admin) }. + to_not change { Project.count } - it "should respond with 201 on success" do - post api("/projects/user/#{user.id}", admin), name: 'foo' - response.status.should == 201 - end - - it 'should respond with 400 on failure' do - post api("/projects/user/#{user.id}", admin) - response.status.should == 400 - json_response['message']['creator'].should == ['can\'t be blank'] - json_response['message']['namespace'].should == ['can\'t be blank'] - json_response['message']['name'].should == [ + expect(response.status).to eq(400) + expect(json_response['message']['name']).to eq([ 'can\'t be blank', 'is too short (minimum is 0 characters)', - 'can contain only letters, digits, \'_\', \'-\' and \'.\' and '\ - 'space. It must start with letter, digit or \'_\'.' - ] - json_response['message']['path'].should == [ + Gitlab::Regex.project_regex_message + ]) + expect(json_response['message']['path']).to eq([ 'can\'t be blank', 'is too short (minimum is 0 characters)', - 'can contain only letters, digits, \'_\', \'-\' and \'.\'. It must '\ - 'start with letter, digit or \'_\', optionally preceeded by \'.\'. '\ - 'It must not end in \'.git\'.' - ] + Gitlab::Regex.send(:default_regex_message) + ]) end - it "should assign attributes to project" do + it 'should assign attributes to project' do project = attributes_for(:project, { description: Faker::Lorem.sentence, issues_enabled: false, @@ -227,226 +268,217 @@ describe API::API, api: true do project.each_pair do |k,v| next if k == :path - json_response[k.to_s].should == v + expect(json_response[k.to_s]).to eq(v) end end - it "should set a project as public" do + it 'should set a project as public' do project = attributes_for(:project, :public) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_true - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC + expect(json_response['public']).to be_truthy + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC) end - it "should set a project as public using :public" do + it 'should set a project as public using :public' do project = attributes_for(:project, { public: true }) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_true - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC + expect(json_response['public']).to be_truthy + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PUBLIC) end - it "should set a project as internal" do + it 'should set a project as internal' do project = attributes_for(:project, :internal) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL) end - it "should set a project as internal overriding :public" do + it 'should set a project as internal overriding :public' do project = attributes_for(:project, :internal, { public: true }) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::INTERNAL) end - it "should set a project as private" do + it 'should set a project as private' do project = attributes_for(:project, :private) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE) end - it "should set a project as private using :public" do + it 'should set a project as private using :public' do project = attributes_for(:project, { public: false }) post api("/projects/user/#{user.id}", admin), project - json_response['public'].should be_false - json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE + expect(json_response['public']).to be_falsey + expect(json_response['visibility_level']).to eq(Gitlab::VisibilityLevel::PRIVATE) end end - describe "GET /projects/:id" do + describe 'GET /projects/:id' do before { project } before { project_member } - it "should return a project by id" do + it 'should return a project by id' do get api("/projects/#{project.id}", user) - response.status.should == 200 - json_response['name'].should == project.name - json_response['owner']['username'].should == user.username + expect(response.status).to eq(200) + expect(json_response['name']).to eq(project.name) + expect(json_response['owner']['username']).to eq(user.username) end - it "should return a project by path name" do + it 'should return a project by path name' do get api("/projects/#{project.id}", user) - response.status.should == 200 - json_response['name'].should == project.name + expect(response.status).to eq(200) + expect(json_response['name']).to eq(project.name) end - it "should return a 404 error if not found" do - get api("/projects/42", user) - response.status.should == 404 - json_response['message'].should == '404 Not Found' + it 'should return a 404 error if not found' do + get api('/projects/42', user) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Project Not Found') end - it "should return a 404 error if user is not a member" do + it 'should return a 404 error if user is not a member' do other_user = create(:user) get api("/projects/#{project.id}", other_user) - response.status.should == 404 + expect(response.status).to eq(404) end describe 'permissions' do context 'personal project' do - before do + it 'Sets project access and returns 200' do project.team << [user, :master] get api("/projects/#{project.id}", user) - end - it { response.status.should == 200 } - it { json_response['permissions']["project_access"]["access_level"].should == Gitlab::Access::MASTER } - it { json_response['permissions']["group_access"].should be_nil } + expect(response.status).to eq(200) + expect(json_response['permissions']['project_access']['access_level']). + to eq(Gitlab::Access::MASTER) + expect(json_response['permissions']['group_access']).to be_nil + end end context 'group project' do - before do + it 'should set the owner and return 200' do project2 = create(:project, group: create(:group)) project2.group.add_owner(user) get api("/projects/#{project2.id}", user) - end - it { response.status.should == 200 } - it { json_response['permissions']["project_access"].should be_nil } - it { json_response['permissions']["group_access"]["access_level"].should == Gitlab::Access::OWNER } + expect(response.status).to eq(200) + expect(json_response['permissions']['project_access']).to be_nil + expect(json_response['permissions']['group_access']['access_level']). + to eq(Gitlab::Access::OWNER) + end end end end - describe "GET /projects/:id/events" do - before { project_member } + describe 'GET /projects/:id/events' do + before { project_member2 } - it "should return a project events" do + it 'should return a project events' do get api("/projects/#{project.id}/events", user) - response.status.should == 200 + expect(response.status).to eq(200) json_event = json_response.first - json_event['action_name'].should == 'joined' - json_event['project_id'].to_i.should == project.id + expect(json_event['action_name']).to eq('joined') + expect(json_event['project_id'].to_i).to eq(project.id) + expect(json_event['author_username']).to eq(user3.username) end - it "should return a 404 error if not found" do - get api("/projects/42/events", user) - response.status.should == 404 - json_response['message'].should == '404 Not Found' + it 'should return a 404 error if not found' do + get api('/projects/42/events', user) + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Project Not Found') end - it "should return a 404 error if user is not a member" do + it 'should return a 404 error if user is not a member' do other_user = create(:user) get api("/projects/#{project.id}/events", other_user) - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "GET /projects/:id/snippets" do + describe 'GET /projects/:id/snippets' do before { snippet } - it "should return an array of project snippets" do + it 'should return an array of project snippets' do get api("/projects/#{project.id}/snippets", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == snippet.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(snippet.title) end end - describe "GET /projects/:id/snippets/:snippet_id" do - it "should return a project snippet" do + describe 'GET /projects/:id/snippets/:snippet_id' do + it 'should return a project snippet' do get api("/projects/#{project.id}/snippets/#{snippet.id}", user) - response.status.should == 200 - json_response['title'].should == snippet.title + expect(response.status).to eq(200) + expect(json_response['title']).to eq(snippet.title) end - it "should return a 404 error if snippet id not found" do + it 'should return a 404 error if snippet id not found' do get api("/projects/#{project.id}/snippets/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "POST /projects/:id/snippets" do - it "should create a new project snippet" do - post api("/projects/#{project.id}/snippets", user), - title: 'api test', file_name: 'sample.rb', code: 'test' - response.status.should == 201 - json_response['title'].should == 'api test' - end - - it "should return a 400 error if title is not given" do + describe 'POST /projects/:id/snippets' do + it 'should create a new project snippet' do post api("/projects/#{project.id}/snippets", user), - file_name: 'sample.rb', code: 'test' - response.status.should == 400 + title: 'api test', file_name: 'sample.rb', code: 'test', + visibility_level: '0' + expect(response.status).to eq(201) + expect(json_response['title']).to eq('api test') end - it "should return a 400 error if file_name not given" do - post api("/projects/#{project.id}/snippets", user), - title: 'api test', code: 'test' - response.status.should == 400 - end - - it "should return a 400 error if code not given" do - post api("/projects/#{project.id}/snippets", user), - title: 'api test', file_name: 'sample.rb' - response.status.should == 400 + it 'should return a 400 error if invalid snippet is given' do + post api("/projects/#{project.id}/snippets", user) + expect(status).to eq(400) end end - describe "PUT /projects/:id/snippets/:shippet_id" do - it "should update an existing project snippet" do + describe 'PUT /projects/:id/snippets/:shippet_id' do + it 'should update an existing project snippet' do put api("/projects/#{project.id}/snippets/#{snippet.id}", user), code: 'updated code' - response.status.should == 200 - json_response['title'].should == 'example' - snippet.reload.content.should == 'updated code' + expect(response.status).to eq(200) + expect(json_response['title']).to eq('example') + expect(snippet.reload.content).to eq('updated code') end - it "should update an existing project snippet with new title" do + it 'should update an existing project snippet with new title' do put api("/projects/#{project.id}/snippets/#{snippet.id}", user), title: 'other api test' - response.status.should == 200 - json_response['title'].should == 'other api test' + expect(response.status).to eq(200) + expect(json_response['title']).to eq('other api test') end end - describe "DELETE /projects/:id/snippets/:snippet_id" do + describe 'DELETE /projects/:id/snippets/:snippet_id' do before { snippet } - it "should delete existing project snippet" do + it 'should delete existing project snippet' do expect { delete api("/projects/#{project.id}/snippets/#{snippet.id}", user) }.to change { Snippet.count }.by(-1) - response.status.should == 200 + expect(response.status).to eq(200) end it 'should return 404 when deleting unknown snippet id' do delete api("/projects/#{project.id}/snippets/1234", user) - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "GET /projects/:id/snippets/:snippet_id/raw" do - it "should get a raw project snippet" do + describe 'GET /projects/:id/snippets/:snippet_id/raw' do + it 'should get a raw project snippet' do get api("/projects/#{project.id}/snippets/#{snippet.id}/raw", user) - response.status.should == 200 + expect(response.status).to eq(200) end - it "should return a 404 error if raw project snippet not found" do + it 'should return a 404 error if raw project snippet not found' do get api("/projects/#{project.id}/snippets/5555/raw", user) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -454,51 +486,51 @@ describe API::API, api: true do let(:deploy_keys_project) { create(:deploy_keys_project, project: project) } let(:deploy_key) { deploy_keys_project.deploy_key } - describe "GET /projects/:id/keys" do + describe 'GET /projects/:id/keys' do before { deploy_key } - it "should return array of ssh keys" do + it 'should return array of ssh keys' do get api("/projects/#{project.id}/keys", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == deploy_key.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(deploy_key.title) end end - describe "GET /projects/:id/keys/:key_id" do - it "should return a single key" do + describe 'GET /projects/:id/keys/:key_id' do + it 'should return a single key' do get api("/projects/#{project.id}/keys/#{deploy_key.id}", user) - response.status.should == 200 - json_response['title'].should == deploy_key.title + expect(response.status).to eq(200) + expect(json_response['title']).to eq(deploy_key.title) end - it "should return 404 Not Found with invalid ID" do + it 'should return 404 Not Found with invalid ID' do get api("/projects/#{project.id}/keys/404", user) - response.status.should == 404 + expect(response.status).to eq(404) end end - describe "POST /projects/:id/keys" do - it "should not create an invalid ssh key" do - post api("/projects/#{project.id}/keys", user), { title: "invalid key" } - response.status.should == 400 - json_response['message']['key'].should == [ + describe 'POST /projects/:id/keys' do + it 'should not create an invalid ssh key' do + post api("/projects/#{project.id}/keys", user), { title: 'invalid key' } + expect(response.status).to eq(400) + expect(json_response['message']['key']).to eq([ 'can\'t be blank', 'is too short (minimum is 0 characters)', 'is invalid' - ] + ]) end it 'should not create a key without title' do post api("/projects/#{project.id}/keys", user), key: 'some key' - response.status.should == 400 - json_response['message']['title'].should == [ + expect(response.status).to eq(400) + expect(json_response['message']['title']).to eq([ 'can\'t be blank', 'is too short (minimum is 0 characters)' - ] + ]) end - it "should create new ssh key" do + it 'should create new ssh key' do key_attrs = attributes_for :key expect { post api("/projects/#{project.id}/keys", user), key_attrs @@ -506,18 +538,18 @@ describe API::API, api: true do end end - describe "DELETE /projects/:id/keys/:key_id" do + describe 'DELETE /projects/:id/keys/:key_id' do before { deploy_key } - it "should delete existing key" do + it 'should delete existing key' do expect { delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user) }.to change{ project.deploy_keys.count }.by(-1) end - it "should return 404 Not Found with invalid ID" do + it 'should return 404 Not Found with invalid ID' do delete api("/projects/#{project.id}/keys/404", user) - response.status.should == 404 + expect(response.status).to eq(404) end end end @@ -526,70 +558,70 @@ describe API::API, api: true do let(:project_fork_target) { create(:project) } let(:project_fork_source) { create(:project, :public) } - describe "POST /projects/:id/fork/:forked_from_id" do + describe 'POST /projects/:id/fork/:forked_from_id' do let(:new_project_fork_source) { create(:project, :public) } it "shouldn't available for non admin users" do post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user) - response.status.should == 403 + expect(response.status).to eq(403) end - it "should allow project to be forked from an existing project" do - project_fork_target.forked?.should_not be_true + it 'should allow project to be forked from an existing project' do + expect(project_fork_target.forked?).not_to be_truthy post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) - response.status.should == 201 + expect(response.status).to eq(201) project_fork_target.reload - project_fork_target.forked_from_project.id.should == project_fork_source.id - project_fork_target.forked_project_link.should_not be_nil - project_fork_target.forked?.should be_true + expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) + expect(project_fork_target.forked_project_link).not_to be_nil + expect(project_fork_target.forked?).to be_truthy end - it "should fail if forked_from project which does not exist" do + it 'should fail if forked_from project which does not exist' do post api("/projects/#{project_fork_target.id}/fork/9999", admin) - response.status.should == 404 + expect(response.status).to eq(404) end - it "should fail with 409 if already forked" do + it 'should fail with 409 if already forked' do post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) project_fork_target.reload - project_fork_target.forked_from_project.id.should == project_fork_source.id + expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) post api("/projects/#{project_fork_target.id}/fork/#{new_project_fork_source.id}", admin) - response.status.should == 409 + expect(response.status).to eq(409) project_fork_target.reload - project_fork_target.forked_from_project.id.should == project_fork_source.id - project_fork_target.forked?.should be_true + expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id) + expect(project_fork_target.forked?).to be_truthy end end - describe "DELETE /projects/:id/fork" do + describe 'DELETE /projects/:id/fork' do it "shouldn't available for non admin users" do delete api("/projects/#{project_fork_target.id}/fork", user) - response.status.should == 403 + expect(response.status).to eq(403) end - it "should make forked project unforked" do + it 'should make forked project unforked' do post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", admin) project_fork_target.reload - project_fork_target.forked_from_project.should_not be_nil - project_fork_target.forked?.should be_true + expect(project_fork_target.forked_from_project).not_to be_nil + expect(project_fork_target.forked?).to be_truthy delete api("/projects/#{project_fork_target.id}/fork", admin) - response.status.should == 200 + expect(response.status).to eq(200) project_fork_target.reload - project_fork_target.forked_from_project.should be_nil - project_fork_target.forked?.should_not be_true + expect(project_fork_target.forked_from_project).to be_nil + expect(project_fork_target.forked?).not_to be_truthy end - it "should be idempotent if not forked" do - project_fork_target.forked_from_project.should be_nil + it 'should be idempotent if not forked' do + expect(project_fork_target.forked_from_project).to be_nil delete api("/projects/#{project_fork_target.id}/fork", admin) - response.status.should == 200 - project_fork_target.reload.forked_from_project.should be_nil + expect(response.status).to eq(200) + expect(project_fork_target.reload.forked_from_project).to be_nil end end end - describe "GET /projects/search/:query" do + describe 'GET /projects/search/:query' do let!(:query) { 'query'} let!(:search) { create(:empty_project, name: query, creator_id: user.id, namespace: user.namespace) } let!(:pre) { create(:empty_project, name: "pre_#{query}", creator_id: user.id, namespace: user.namespace) } @@ -601,68 +633,185 @@ describe API::API, api: true do let!(:public) { create(:empty_project, :public, name: "public #{query}") } let!(:unfound_public) { create(:empty_project, :public, name: 'unfound public') } - context "when unauthenticated" do - it "should return authentication error" do + context 'when unauthenticated' do + it 'should return authentication error' do get api("/projects/search/#{query}") - response.status.should == 401 + expect(response.status).to eq(401) end end - context "when authenticated" do - it "should return an array of projects" do + context 'when authenticated' do + it 'should return an array of projects' do get api("/projects/search/#{query}",user) - response.status.should == 200 - json_response.should be_an Array - json_response.size.should == 6 - json_response.each {|project| project['name'].should =~ /.*query.*/} + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(6) + json_response.each {|project| expect(project['name']).to match(/.*query.*/)} end end - context "when authenticated as a different user" do - it "should return matching public projects" do + context 'when authenticated as a different user' do + it 'should return matching public projects' do get api("/projects/search/#{query}", user2) - response.status.should == 200 - json_response.should be_an Array - json_response.size.should == 2 - json_response.each {|project| project['name'].should =~ /(internal|public) query/} + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.size).to eq(2) + json_response.each {|project| expect(project['name']).to match(/(internal|public) query/)} end end end - describe "DELETE /projects/:id" do - context "when authenticated as user" do - it "should remove project" do + describe 'PUT /projects/:id̈́' do + before { project } + before { user } + before { user3 } + before { user4 } + before { project3 } + before { project4 } + before { project_member3 } + before { project_member2 } + + context 'when unauthenticated' do + it 'should return authentication error' do + project_param = { name: 'bar' } + put api("/projects/#{project.id}"), project_param + expect(response.status).to eq(401) + end + end + + context 'when authenticated as project owner' do + it 'should update name' do + project_param = { name: 'bar' } + put api("/projects/#{project.id}", user), project_param + expect(response.status).to eq(200) + project_param.each_pair do |k, v| + expect(json_response[k.to_s]).to eq(v) + end + end + + it 'should update visibility_level' do + project_param = { visibility_level: 20 } + put api("/projects/#{project3.id}", user), project_param + expect(response.status).to eq(200) + project_param.each_pair do |k, v| + expect(json_response[k.to_s]).to eq(v) + end + end + + it 'should not update name to existing name' do + project_param = { name: project3.name } + put api("/projects/#{project.id}", user), project_param + expect(response.status).to eq(400) + expect(json_response['message']['name']).to eq(['has already been taken']) + end + + it 'should update path & name to existing path & name in different namespace' do + project_param = { path: project4.path, name: project4.name } + put api("/projects/#{project3.id}", user), project_param + expect(response.status).to eq(200) + project_param.each_pair do |k, v| + expect(json_response[k.to_s]).to eq(v) + end + end + end + + context 'when authenticated as project master' do + it 'should update path' do + project_param = { path: 'bar' } + put api("/projects/#{project3.id}", user4), project_param + expect(response.status).to eq(200) + project_param.each_pair do |k, v| + expect(json_response[k.to_s]).to eq(v) + end + end + + it 'should update other attributes' do + project_param = { issues_enabled: true, + wiki_enabled: true, + snippets_enabled: true, + merge_requests_enabled: true, + description: 'new description' } + + put api("/projects/#{project3.id}", user4), project_param + expect(response.status).to eq(200) + project_param.each_pair do |k, v| + expect(json_response[k.to_s]).to eq(v) + end + end + + it 'should not update path to existing path' do + project_param = { path: project.path } + put api("/projects/#{project3.id}", user4), project_param + expect(response.status).to eq(400) + expect(json_response['message']['path']).to eq(['has already been taken']) + end + + it 'should not update name' do + project_param = { name: 'bar' } + put api("/projects/#{project3.id}", user4), project_param + expect(response.status).to eq(403) + end + + it 'should not update visibility_level' do + project_param = { visibility_level: 20 } + put api("/projects/#{project3.id}", user4), project_param + expect(response.status).to eq(403) + end + end + + context 'when authenticated as project developer' do + it 'should not update other attributes' do + project_param = { path: 'bar', + issues_enabled: true, + wiki_enabled: true, + snippets_enabled: true, + merge_requests_enabled: true, + description: 'new description' } + put api("/projects/#{project.id}", user3), project_param + expect(response.status).to eq(403) + end + end + end + + describe 'DELETE /projects/:id' do + context 'when authenticated as user' do + it 'should remove project' do + expect(GitlabShellWorker).to( + receive(:perform_async).with(:remove_repository, + /#{project.path_with_namespace}/) + ).twice + delete api("/projects/#{project.id}", user) - response.status.should == 200 + expect(response.status).to eq(200) end - it "should not remove a project if not an owner" do + it 'should not remove a project if not an owner' do user3 = create(:user) project.team << [user3, :developer] delete api("/projects/#{project.id}", user3) - response.status.should == 403 + expect(response.status).to eq(403) end - it "should not remove a non existing project" do - delete api("/projects/1328", user) - response.status.should == 404 + it 'should not remove a non existing project' do + delete api('/projects/1328', user) + expect(response.status).to eq(404) end - it "should not remove a project not attached to user" do + it 'should not remove a project not attached to user' do delete api("/projects/#{project.id}", user2) - response.status.should == 404 + expect(response.status).to eq(404) end end - context "when authenticated as admin" do - it "should remove any existing project" do + context 'when authenticated as admin' do + it 'should remove any existing project' do delete api("/projects/#{project.id}", admin) - response.status.should == 200 + expect(response.status).to eq(200) end - it "should not remove a non existing project" do - delete api("/projects/1328", admin) - response.status.should == 404 + it 'should not remove a non existing project' do + delete api('/projects/1328', admin) + expect(response.status).to eq(404) end end end diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb index 6e54839b677..729970153d1 100644 --- a/spec/requests/api/repositories_spec.rb +++ b/spec/requests/api/repositories_spec.rb @@ -16,9 +16,9 @@ describe API::API, api: true do describe "GET /projects/:id/repository/tags" do it "should return an array of project tags" do get api("/projects/#{project.id}/repository/tags", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first['name'].should == project.repo.tags.sort_by(&:name).reverse.first.name + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq(project.repo.tags.sort_by(&:name).reverse.first.name) end end @@ -29,60 +29,62 @@ describe API::API, api: true do tag_name: 'v7.0.1', ref: 'master' - response.status.should == 201 - json_response['name'].should == 'v7.0.1' + expect(response.status).to eq(201) + expect(json_response['name']).to eq('v7.0.1') end end - # TODO: fix this test for CI - #context 'annotated tag' do - #it 'should create a new annotated tag' do - #post api("/projects/#{project.id}/repository/tags", user), - #tag_name: 'v7.1.0', - #ref: 'master', - #message: 'tag message' + context 'annotated tag' do + it 'should create a new annotated tag' do + # Identity must be set in .gitconfig to create annotated tag. + repo_path = project.repository.path_to_repo + system(*%W(git --git-dir=#{repo_path} config user.name #{user.name})) + system(*%W(git --git-dir=#{repo_path} config user.email #{user.email})) - #response.status.should == 201 - #json_response['name'].should == 'v7.1.0' - # The message is not part of the JSON response. - # Additional changes to the gitlab_git gem may be required. - # json_response['message'].should == 'tag message' - #end - #end + post api("/projects/#{project.id}/repository/tags", user), + tag_name: 'v7.1.0', + ref: 'master', + message: 'Release 7.1.0' + + expect(response.status).to eq(201) + expect(json_response['name']).to eq('v7.1.0') + expect(json_response['message']).to eq('Release 7.1.0') + end + end it 'should deny for user without push access' do post api("/projects/#{project.id}/repository/tags", user2), tag_name: 'v1.9.0', ref: '621491c677087aa243f165eab467bfdfbee00be1' - response.status.should == 403 + expect(response.status).to eq(403) end it 'should return 400 if tag name is invalid' do post api("/projects/#{project.id}/repository/tags", user), tag_name: 'v 1.0.0', ref: 'master' - response.status.should == 400 - json_response['message'].should == 'Tag name invalid' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Tag name invalid') end it 'should return 400 if tag already exists' do post api("/projects/#{project.id}/repository/tags", user), tag_name: 'v8.0.0', ref: 'master' - response.status.should == 201 + expect(response.status).to eq(201) post api("/projects/#{project.id}/repository/tags", user), tag_name: 'v8.0.0', ref: 'master' - response.status.should == 400 - json_response['message'].should == 'Tag already exists' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Tag already exists') end it 'should return 400 if ref name is invalid' do post api("/projects/#{project.id}/repository/tags", user), tag_name: 'mytag', ref: 'foo' - response.status.should == 400 - json_response['message'].should == 'Invalid reference name' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('Invalid reference name') end end @@ -92,19 +94,27 @@ describe API::API, api: true do it "should return project commits" do get api("/projects/#{project.id}/repository/tree", user) - response.status.should == 200 + expect(response.status).to eq(200) + + expect(json_response).to be_an Array + expect(json_response.first['name']).to eq('encoding') + expect(json_response.first['type']).to eq('tree') + expect(json_response.first['mode']).to eq('040000') + end + + it 'should return a 404 for unknown ref' do + get api("/projects/#{project.id}/repository/tree?ref_name=foo", user) + expect(response.status).to eq(404) - json_response.should be_an Array - json_response.first['name'].should == 'encoding' - json_response.first['type'].should == 'tree' - json_response.first['mode'].should == '040000' + expect(json_response).to be_an Object + json_response['message'] == '404 Tree Not Found' end end context "unauthorized user" do it "should not return project commits" do get api("/projects/#{project.id}/repository/tree") - response.status.should == 401 + expect(response.status).to eq(401) end end end @@ -112,36 +122,44 @@ describe API::API, api: true do describe "GET /projects/:id/repository/blobs/:sha" do it "should get the raw file contents" do get api("/projects/#{project.id}/repository/blobs/master?filepath=README.md", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return 404 for invalid branch_name" do get api("/projects/#{project.id}/repository/blobs/invalid_branch_name?filepath=README.md", user) - response.status.should == 404 + expect(response.status).to eq(404) end it "should return 404 for invalid file" do get api("/projects/#{project.id}/repository/blobs/master?filepath=README.invalid", user) - response.status.should == 404 + expect(response.status).to eq(404) end it "should return a 400 error if filepath is missing" do get api("/projects/#{project.id}/repository/blobs/master", user) - response.status.should == 400 + expect(response.status).to eq(400) end end describe "GET /projects/:id/repository/commits/:sha/blob" do it "should get the raw file contents" do get api("/projects/#{project.id}/repository/commits/master/blob?filepath=README.md", user) - response.status.should == 200 + expect(response.status).to eq(200) end end describe "GET /projects/:id/repository/raw_blobs/:sha" do it "should get the raw file contents" do get api("/projects/#{project.id}/repository/raw_blobs/#{sample_blob.oid}", user) - response.status.should == 200 + expect(response.status).to eq(200) + end + + it 'should return a 404 for unknown blob' do + get api("/projects/#{project.id}/repository/raw_blobs/123456", user) + expect(response.status).to eq(404) + + expect(json_response).to be_an Object + json_response['message'] == '404 Blob Not Found' end end @@ -149,83 +167,83 @@ describe API::API, api: true do it "should get the archive" do get api("/projects/#{project.id}/repository/archive", user) repo_name = project.repository.name.gsub("\.git", "") - response.status.should == 200 - response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/ - response.content_type.should == MIME::Types.type_for('file.tar.gz').first.content_type + expect(response.status).to eq(200) + expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.tar.gz\"/) + expect(response.content_type).to eq(MIME::Types.type_for('file.tar.gz').first.content_type) end it "should get the archive.zip" do get api("/projects/#{project.id}/repository/archive.zip", user) repo_name = project.repository.name.gsub("\.git", "") - response.status.should == 200 - response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.zip\"/ - response.content_type.should == MIME::Types.type_for('file.zip').first.content_type + expect(response.status).to eq(200) + expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.zip\"/) + expect(response.content_type).to eq(MIME::Types.type_for('file.zip').first.content_type) end it "should get the archive.tar.bz2" do get api("/projects/#{project.id}/repository/archive.tar.bz2", user) repo_name = project.repository.name.gsub("\.git", "") - response.status.should == 200 - response.headers['Content-Disposition'].should =~ /filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/ - response.content_type.should == MIME::Types.type_for('file.tar.bz2').first.content_type + expect(response.status).to eq(200) + expect(response.headers['Content-Disposition']).to match(/filename\=\"#{repo_name}\-[^\.]+\.tar.bz2\"/) + expect(response.content_type).to eq(MIME::Types.type_for('file.tar.bz2').first.content_type) end it "should return 404 for invalid sha" do get api("/projects/#{project.id}/repository/archive/?sha=xxx", user) - response.status.should == 404 + expect(response.status).to eq(404) end end describe 'GET /projects/:id/repository/compare' do it "should compare branches" do get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'feature' - response.status.should == 200 - json_response['commits'].should be_present - json_response['diffs'].should be_present + expect(response.status).to eq(200) + expect(json_response['commits']).to be_present + expect(json_response['diffs']).to be_present end it "should compare tags" do get api("/projects/#{project.id}/repository/compare", user), from: 'v1.0.0', to: 'v1.1.0' - response.status.should == 200 - json_response['commits'].should be_present - json_response['diffs'].should be_present + expect(response.status).to eq(200) + expect(json_response['commits']).to be_present + expect(json_response['diffs']).to be_present end it "should compare commits" do get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.id, to: sample_commit.parent_id - response.status.should == 200 - json_response['commits'].should be_empty - json_response['diffs'].should be_empty - json_response['compare_same_ref'].should be_false + expect(response.status).to eq(200) + expect(json_response['commits']).to be_empty + expect(json_response['diffs']).to be_empty + expect(json_response['compare_same_ref']).to be_falsey end it "should compare commits in reverse order" do get api("/projects/#{project.id}/repository/compare", user), from: sample_commit.parent_id, to: sample_commit.id - response.status.should == 200 - json_response['commits'].should be_present - json_response['diffs'].should be_present + expect(response.status).to eq(200) + expect(json_response['commits']).to be_present + expect(json_response['diffs']).to be_present end it "should compare same refs" do get api("/projects/#{project.id}/repository/compare", user), from: 'master', to: 'master' - response.status.should == 200 - json_response['commits'].should be_empty - json_response['diffs'].should be_empty - json_response['compare_same_ref'].should be_true + expect(response.status).to eq(200) + expect(json_response['commits']).to be_empty + expect(json_response['diffs']).to be_empty + expect(json_response['compare_same_ref']).to be_truthy end end describe 'GET /projects/:id/repository/contributors' do it 'should return valid data' do get api("/projects/#{project.id}/repository/contributors", user) - response.status.should == 200 - json_response.should be_an Array + expect(response.status).to eq(200) + expect(json_response).to be_an Array contributor = json_response.first - contributor['email'].should == 'dmitriy.zaporozhets@gmail.com' - contributor['name'].should == 'Dmitriy Zaporozhets' - contributor['commits'].should == 13 - contributor['additions'].should == 0 - contributor['deletions'].should == 0 + expect(contributor['email']).to eq('dmitriy.zaporozhets@gmail.com') + expect(contributor['name']).to eq('Dmitriy Zaporozhets') + expect(contributor['commits']).to eq(13) + expect(contributor['additions']).to eq(0) + expect(contributor['deletions']).to eq(0) end end end diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb index f883c9e028a..51c543578df 100644 --- a/spec/requests/api/services_spec.rb +++ b/spec/requests/api/services_spec.rb @@ -9,13 +9,13 @@ describe API::API, api: true do it "should update gitlab-ci settings" do put api("/projects/#{project.id}/services/gitlab-ci", user), token: 'secret-token', project_url: "http://ci.example.com/projects/1" - response.status.should == 200 + expect(response.status).to eq(200) end it "should return if required fields missing" do put api("/projects/#{project.id}/services/gitlab-ci", user), project_url: "http://ci.example.com/projects/1", active: true - response.status.should == 400 + expect(response.status).to eq(400) end end @@ -23,8 +23,34 @@ describe API::API, api: true do it "should update gitlab-ci settings" do delete api("/projects/#{project.id}/services/gitlab-ci", user) - response.status.should == 200 - project.gitlab_ci_service.should be_nil + expect(response.status).to eq(200) + expect(project.gitlab_ci_service).to be_nil + end + end + + describe 'PUT /projects/:id/services/hipchat' do + it 'should update hipchat settings' do + put api("/projects/#{project.id}/services/hipchat", user), + token: 'secret-token', room: 'test' + + expect(response.status).to eq(200) + expect(project.hipchat_service).not_to be_nil + end + + it 'should return if required fields missing' do + put api("/projects/#{project.id}/services/gitlab-ci", user), + token: 'secret-token', active: true + + expect(response.status).to eq(400) + end + end + + describe 'DELETE /projects/:id/services/hipchat' do + it 'should delete hipchat settings' do + delete api("/projects/#{project.id}/services/hipchat", user) + + expect(response.status).to eq(200) + expect(project.hipchat_service).to be_nil end end end diff --git a/spec/requests/api/session_spec.rb b/spec/requests/api/session_spec.rb index 013f425d6ce..fbd57b34a58 100644 --- a/spec/requests/api/session_spec.rb +++ b/spec/requests/api/session_spec.rb @@ -9,43 +9,69 @@ describe API::API, api: true do context "when valid password" do it "should return private token" do post api("/session"), email: user.email, password: '12345678' - response.status.should == 201 + expect(response.status).to eq(201) - json_response['email'].should == user.email - json_response['private_token'].should == user.private_token - json_response['is_admin'].should == user.is_admin? - json_response['can_create_project'].should == user.can_create_project? - json_response['can_create_group'].should == user.can_create_group? + expect(json_response['email']).to eq(user.email) + expect(json_response['private_token']).to eq(user.private_token) + expect(json_response['is_admin']).to eq(user.is_admin?) + expect(json_response['can_create_project']).to eq(user.can_create_project?) + expect(json_response['can_create_group']).to eq(user.can_create_group?) + end + end + + context 'when email has case-typo and password is valid' do + it 'should return private token' do + post api('/session'), email: user.email.upcase, password: '12345678' + expect(response.status).to eq 201 + + expect(json_response['email']).to eq user.email + expect(json_response['private_token']).to eq user.private_token + expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['can_create_project']).to eq user.can_create_project? + expect(json_response['can_create_group']).to eq user.can_create_group? + end + end + + context 'when login has case-typo and password is valid' do + it 'should return private token' do + post api('/session'), login: user.username.upcase, password: '12345678' + expect(response.status).to eq 201 + + expect(json_response['email']).to eq user.email + expect(json_response['private_token']).to eq user.private_token + expect(json_response['is_admin']).to eq user.is_admin? + expect(json_response['can_create_project']).to eq user.can_create_project? + expect(json_response['can_create_group']).to eq user.can_create_group? end end context "when invalid password" do it "should return authentication error" do post api("/session"), email: user.email, password: '123' - response.status.should == 401 + expect(response.status).to eq(401) - json_response['email'].should be_nil - json_response['private_token'].should be_nil + expect(json_response['email']).to be_nil + expect(json_response['private_token']).to be_nil end end context "when empty password" do it "should return authentication error" do post api("/session"), email: user.email - response.status.should == 401 + expect(response.status).to eq(401) - json_response['email'].should be_nil - json_response['private_token'].should be_nil + expect(json_response['email']).to be_nil + expect(json_response['private_token']).to be_nil end end context "when empty name" do it "should return authentication error" do post api("/session"), password: user.password - response.status.should == 401 + expect(response.status).to eq(401) - json_response['email'].should be_nil - json_response['private_token'].should be_nil + expect(json_response['email']).to be_nil + expect(json_response['private_token']).to be_nil end end end diff --git a/spec/requests/api/system_hooks_spec.rb b/spec/requests/api/system_hooks_spec.rb index 5784ae8c23a..a9d86bbce6c 100644 --- a/spec/requests/api/system_hooks_spec.rb +++ b/spec/requests/api/system_hooks_spec.rb @@ -13,23 +13,23 @@ describe API::API, api: true do context "when no user" do it "should return authentication error" do get api("/hooks") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when not an admin" do it "should return forbidden error" do get api("/hooks", user) - response.status.should == 403 + expect(response.status).to eq(403) end end context "when authenticated as admin" do it "should return an array of hooks" do get api("/hooks", admin) - response.status.should == 200 - json_response.should be_an Array - json_response.first['url'].should == hook.url + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['url']).to eq(hook.url) end end end @@ -43,7 +43,7 @@ describe API::API, api: true do it "should respond with 400 if url not given" do post api("/hooks", admin) - response.status.should == 400 + expect(response.status).to eq(400) end it "should not create new hook without url" do @@ -56,13 +56,13 @@ describe API::API, api: true do describe "GET /hooks/:id" do it "should return hook by id" do get api("/hooks/#{hook.id}", admin) - response.status.should == 200 - json_response['event_name'].should == 'project_create' + expect(response.status).to eq(200) + expect(json_response['event_name']).to eq('project_create') end it "should return 404 on failure" do get api("/hooks/404", admin) - response.status.should == 404 + expect(response.status).to eq(404) end end @@ -75,7 +75,7 @@ describe API::API, api: true do it "should return success if hook id not found" do delete api("/hooks/12345", admin) - response.status.should == 200 + expect(response.status).to eq(200) end end end diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index bc1598273be..081400cdedd 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -11,30 +11,30 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/users") - response.status.should == 401 + expect(response.status).to eq(401) end end context "when authenticated" do it "should return an array of users" do get api("/users", user) - response.status.should == 200 - json_response.should be_an Array + expect(response.status).to eq(200) + expect(json_response).to be_an Array username = user.username - json_response.detect { + expect(json_response.detect { |user| user['username'] == username - }['username'].should == username + }['username']).to eq(username) end end context "when admin" do it "should return an array of users" do get api("/users", admin) - response.status.should == 200 - json_response.should be_an Array - json_response.first.keys.should include 'email' - json_response.first.keys.should include 'extern_uid' - json_response.first.keys.should include 'can_create_project' + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first.keys).to include 'email' + expect(json_response.first.keys).to include 'identities' + expect(json_response.first.keys).to include 'can_create_project' end end end @@ -42,19 +42,19 @@ describe API::API, api: true do describe "GET /users/:id" do it "should return a user by id" do get api("/users/#{user.id}", user) - response.status.should == 200 - json_response['username'].should == user.username + expect(response.status).to eq(200) + expect(json_response['username']).to eq(user.username) end it "should return a 401 if unauthenticated" do get api("/users/9998") - response.status.should == 401 + expect(response.status).to eq(401) end it "should return a 404 error if user id not found" do get api("/users/9999", user) - response.status.should == 404 - json_response['message'].should == '404 Not found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') end end @@ -69,36 +69,36 @@ describe API::API, api: true do it "should create user with correct attributes" do post api('/users', admin), attributes_for(:user, admin: true, can_create_group: true) - response.status.should == 201 + expect(response.status).to eq(201) user_id = json_response['id'] new_user = User.find(user_id) - new_user.should_not == nil - new_user.admin.should == true - new_user.can_create_group.should == true + expect(new_user).not_to eq(nil) + expect(new_user.admin).to eq(true) + expect(new_user.can_create_group).to eq(true) end it "should create non-admin user" do post api('/users', admin), attributes_for(:user, admin: false, can_create_group: false) - response.status.should == 201 + expect(response.status).to eq(201) user_id = json_response['id'] new_user = User.find(user_id) - new_user.should_not == nil - new_user.admin.should == false - new_user.can_create_group.should == false + expect(new_user).not_to eq(nil) + expect(new_user.admin).to eq(false) + expect(new_user.can_create_group).to eq(false) end it "should create non-admin users by default" do post api('/users', admin), attributes_for(:user) - response.status.should == 201 + expect(response.status).to eq(201) user_id = json_response['id'] new_user = User.find(user_id) - new_user.should_not == nil - new_user.admin.should == false + expect(new_user).not_to eq(nil) + expect(new_user.admin).to eq(false) end it "should return 201 Created on success" do post api("/users", admin), attributes_for(:user, projects_limit: 3) - response.status.should == 201 + expect(response.status).to eq(201) end it "should not create user with invalid email" do @@ -106,22 +106,22 @@ describe API::API, api: true do email: 'invalid email', password: 'password', name: 'test' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 error if name not given' do post api('/users', admin), email: 'test@example.com', password: 'pass1234' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 error if password not given' do post api('/users', admin), email: 'test@example.com', name: 'test' - response.status.should == 400 + expect(response.status).to eq(400) end it "should return 400 error if email not given" do post api('/users', admin), password: 'pass1234', name: 'test' - response.status.should == 400 + expect(response.status).to eq(400) end it 'should return 400 error if user does not validate' do @@ -132,22 +132,20 @@ describe API::API, api: true do name: 'test', bio: 'g' * 256, projects_limit: -1 - response.status.should == 400 - json_response['message']['password']. - should == ['is too short (minimum is 8 characters)'] - json_response['message']['bio']. - should == ['is too long (maximum is 255 characters)'] - json_response['message']['projects_limit']. - should == ['must be greater than or equal to 0'] - json_response['message']['username']. - should == ['can contain only letters, digits, '\ - '\'_\', \'-\' and \'.\'. It must start with letter, digit or '\ - '\'_\', optionally preceeded by \'.\'. It must not end in \'.git\'.'] + expect(response.status).to eq(400) + expect(json_response['message']['password']). + to eq(['is too short (minimum is 8 characters)']) + expect(json_response['message']['bio']). + to eq(['is too long (maximum is 255 characters)']) + expect(json_response['message']['projects_limit']). + to eq(['must be greater than or equal to 0']) + expect(json_response['message']['username']). + to eq([Gitlab::Regex.send(:default_regex_message)]) end it "shouldn't available for non admin users" do post api("/users", user), attributes_for(:user) - response.status.should == 403 + expect(response.status).to eq(403) end context 'with existing user' do @@ -167,8 +165,8 @@ describe API::API, api: true do password: 'password', username: 'foo' }.to change { User.count }.by(0) - response.status.should == 409 - json_response['message'].should == 'Email has already been taken' + expect(response.status).to eq(409) + expect(json_response['message']).to eq('Email has already been taken') end it 'should return 409 conflict error if same username exists' do @@ -179,34 +177,18 @@ describe API::API, api: true do password: 'password', username: 'test' end.to change { User.count }.by(0) - response.status.should == 409 - json_response['message'].should == 'Username has already been taken' + expect(response.status).to eq(409) + expect(json_response['message']).to eq('Username has already been taken') end end end describe "GET /users/sign_up" do - context 'enabled' do - before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(true) - end - - it "should return sign up page if signup is enabled" do - get "/users/sign_up" - response.status.should == 200 - end - end - context 'disabled' do - before do - Gitlab.config.gitlab.stub(:signup_enabled).and_return(false) - end - - it "should redirect to sign in page if signup is disabled" do - get "/users/sign_up" - response.status.should == 302 - response.should redirect_to(new_user_session_path) - end + it "should redirect to sign in page" do + get "/users/sign_up" + expect(response.status).to eq(302) + expect(response).to redirect_to(new_user_session_path) end end @@ -217,55 +199,55 @@ describe API::API, api: true do it "should update user with new bio" do put api("/users/#{user.id}", admin), {bio: 'new test bio'} - response.status.should == 200 - json_response['bio'].should == 'new test bio' - user.reload.bio.should == 'new test bio' + expect(response.status).to eq(200) + expect(json_response['bio']).to eq('new test bio') + expect(user.reload.bio).to eq('new test bio') end it 'should update user with his own email' do put api("/users/#{user.id}", admin), email: user.email - response.status.should == 200 - json_response['email'].should == user.email - user.reload.email.should == user.email + expect(response.status).to eq(200) + expect(json_response['email']).to eq(user.email) + expect(user.reload.email).to eq(user.email) end it 'should update user with his own username' do put api("/users/#{user.id}", admin), username: user.username - response.status.should == 200 - json_response['username'].should == user.username - user.reload.username.should == user.username + expect(response.status).to eq(200) + expect(json_response['username']).to eq(user.username) + expect(user.reload.username).to eq(user.username) end it "should update admin status" do put api("/users/#{user.id}", admin), {admin: true} - response.status.should == 200 - json_response['is_admin'].should == true - user.reload.admin.should == true + expect(response.status).to eq(200) + expect(json_response['is_admin']).to eq(true) + expect(user.reload.admin).to eq(true) end it "should not update admin status" do put api("/users/#{admin_user.id}", admin), {can_create_group: false} - response.status.should == 200 - json_response['is_admin'].should == true - admin_user.reload.admin.should == true - admin_user.can_create_group.should == false + expect(response.status).to eq(200) + expect(json_response['is_admin']).to eq(true) + expect(admin_user.reload.admin).to eq(true) + expect(admin_user.can_create_group).to eq(false) end it "should not allow invalid update" do put api("/users/#{user.id}", admin), {email: 'invalid email'} - response.status.should == 400 - user.reload.email.should_not == 'invalid email' + expect(response.status).to eq(400) + expect(user.reload.email).not_to eq('invalid email') end it "shouldn't available for non admin users" do put api("/users/#{user.id}", user), attributes_for(:user) - response.status.should == 403 + expect(response.status).to eq(403) end it "should return 404 for non-existing user" do put api("/users/999999", admin), {bio: 'update should fail'} - response.status.should == 404 - json_response['message'].should == '404 Not found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') end it 'should return 400 error if user does not validate' do @@ -276,17 +258,15 @@ describe API::API, api: true do name: 'test', bio: 'g' * 256, projects_limit: -1 - response.status.should == 400 - json_response['message']['password']. - should == ['is too short (minimum is 8 characters)'] - json_response['message']['bio']. - should == ['is too long (maximum is 255 characters)'] - json_response['message']['projects_limit']. - should == ['must be greater than or equal to 0'] - json_response['message']['username']. - should == ['can contain only letters, digits, '\ - '\'_\', \'-\' and \'.\'. It must start with letter, digit or '\ - '\'_\', optionally preceeded by \'.\'. It must not end in \'.git\'.'] + expect(response.status).to eq(400) + expect(json_response['message']['password']). + to eq(['is too short (minimum is 8 characters)']) + expect(json_response['message']['bio']). + to eq(['is too long (maximum is 255 characters)']) + expect(json_response['message']['projects_limit']). + to eq(['must be greater than or equal to 0']) + expect(json_response['message']['username']). + to eq([Gitlab::Regex.send(:default_regex_message)]) end context "with existing user" do @@ -298,15 +278,15 @@ describe API::API, api: true do it 'should return 409 conflict error if email address exists' do put api("/users/#{@user.id}", admin), email: 'test@example.com' - response.status.should == 409 - @user.reload.email.should == @user.email + expect(response.status).to eq(409) + expect(@user.reload.email).to eq(@user.email) end it 'should return 409 conflict error if username taken' do @user_id = User.all.last.id put api("/users/#{@user.id}", admin), username: 'test' - response.status.should == 409 - @user.reload.username.should == @user.username + expect(response.status).to eq(409) + expect(@user.reload.username).to eq(@user.username) end end end @@ -316,14 +296,14 @@ describe API::API, api: true do it "should not create invalid ssh key" do post api("/users/#{user.id}/keys", admin), { title: "invalid key" } - response.status.should == 400 - json_response['message'].should == '400 (Bad request) "key" not given' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "key" not given') end it 'should not create key without title' do post api("/users/#{user.id}/keys", admin), key: 'some key' - response.status.should == 400 - json_response['message'].should == '400 (Bad request) "title" not given' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "title" not given') end it "should create ssh key" do @@ -340,24 +320,24 @@ describe API::API, api: true do context 'when unauthenticated' do it 'should return authentication error' do get api("/users/#{user.id}/keys") - response.status.should == 401 + expect(response.status).to eq(401) end end context 'when authenticated' do it 'should return 404 for non-existing user' do get api('/users/999999/keys', admin) - response.status.should == 404 - json_response['message'].should == '404 User Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') end it 'should return array of ssh keys' do user.keys << key user.save get api("/users/#{user.id}/keys", admin) - response.status.should == 200 - json_response.should be_an Array - json_response.first['title'].should == key.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first['title']).to eq(key.title) end end end @@ -368,7 +348,7 @@ describe API::API, api: true do context 'when unauthenticated' do it 'should return authentication error' do delete api("/users/#{user.id}/keys/42") - response.status.should == 401 + expect(response.status).to eq(401) end end @@ -379,21 +359,21 @@ describe API::API, api: true do expect { delete api("/users/#{user.id}/keys/#{key.id}", admin) }.to change { user.keys.count }.by(-1) - response.status.should == 200 + expect(response.status).to eq(200) end it 'should return 404 error if user not found' do user.keys << key user.save delete api("/users/999999/keys/#{key.id}", admin) - response.status.should == 404 - json_response['message'].should == '404 User Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') end it 'should return 404 error if key not foud' do delete api("/users/#{user.id}/keys/42", admin) - response.status.should == 404 - json_response['message'].should == '404 Key Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Key Not Found') end end end @@ -403,41 +383,42 @@ describe API::API, api: true do it "should delete user" do delete api("/users/#{user.id}", admin) - response.status.should == 200 + expect(response.status).to eq(200) expect { User.find(user.id) }.to raise_error ActiveRecord::RecordNotFound - json_response['email'].should == user.email + expect(json_response['email']).to eq(user.email) end it "should not delete for unauthenticated user" do delete api("/users/#{user.id}") - response.status.should == 401 + expect(response.status).to eq(401) end it "shouldn't available for non admin users" do delete api("/users/#{user.id}", user) - response.status.should == 403 + expect(response.status).to eq(403) end it "should return 404 for non-existing user" do delete api("/users/999999", admin) - response.status.should == 404 - json_response['message'].should == '404 User Not Found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 User Not Found') end end describe "GET /user" do it "should return current user" do get api("/user", user) - response.status.should == 200 - json_response['email'].should == user.email - json_response['is_admin'].should == user.is_admin? - json_response['can_create_project'].should == user.can_create_project? - json_response['can_create_group'].should == user.can_create_group? + expect(response.status).to eq(200) + expect(json_response['email']).to eq(user.email) + expect(json_response['is_admin']).to eq(user.is_admin?) + expect(json_response['can_create_project']).to eq(user.can_create_project?) + expect(json_response['can_create_group']).to eq(user.can_create_group?) + expect(json_response['projects_limit']).to eq(user.projects_limit) end it "should return 401 error if user is unauthenticated" do get api("/user") - response.status.should == 401 + expect(response.status).to eq(401) end end @@ -445,7 +426,7 @@ describe API::API, api: true do context "when unauthenticated" do it "should return authentication error" do get api("/user/keys") - response.status.should == 401 + expect(response.status).to eq(401) end end @@ -454,9 +435,9 @@ describe API::API, api: true do user.keys << key user.save get api("/user/keys", user) - response.status.should == 200 - json_response.should be_an Array - json_response.first["title"].should == key.title + expect(response.status).to eq(200) + expect(json_response).to be_an Array + expect(json_response.first["title"]).to eq(key.title) end end end @@ -466,14 +447,14 @@ describe API::API, api: true do user.keys << key user.save get api("/user/keys/#{key.id}", user) - response.status.should == 200 - json_response["title"].should == key.title + expect(response.status).to eq(200) + expect(json_response["title"]).to eq(key.title) end it "should return 404 Not Found within invalid ID" do get api("/user/keys/42", user) - response.status.should == 404 - json_response['message'].should == '404 Not found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') end it "should return 404 error if admin accesses user's ssh key" do @@ -481,8 +462,8 @@ describe API::API, api: true do user.save admin get api("/user/keys/#{key.id}", admin) - response.status.should == 404 - json_response['message'].should == '404 Not found' + expect(response.status).to eq(404) + expect(json_response['message']).to eq('404 Not found') end end @@ -492,29 +473,29 @@ describe API::API, api: true do expect { post api("/user/keys", user), key_attrs }.to change{ user.keys.count }.by(1) - response.status.should == 201 + expect(response.status).to eq(201) end it "should return a 401 error if unauthorized" do post api("/user/keys"), title: 'some title', key: 'some key' - response.status.should == 401 + expect(response.status).to eq(401) end it "should not create ssh key without key" do post api("/user/keys", user), title: 'title' - response.status.should == 400 - json_response['message'].should == '400 (Bad request) "key" not given' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "key" not given') end it 'should not create ssh key without title' do post api('/user/keys', user), key: 'some key' - response.status.should == 400 - json_response['message'].should == '400 (Bad request) "title" not given' + expect(response.status).to eq(400) + expect(json_response['message']).to eq('400 (Bad request) "title" not given') end it "should not create ssh key without title" do post api("/user/keys", user), key: "somekey" - response.status.should == 400 + expect(response.status).to eq(400) end end @@ -525,19 +506,19 @@ describe API::API, api: true do expect { delete api("/user/keys/#{key.id}", user) }.to change{user.keys.count}.by(-1) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return success if key ID not found" do delete api("/user/keys/42", user) - response.status.should == 200 + expect(response.status).to eq(200) end it "should return 401 error if unauthorized" do user.keys << key user.save delete api("/user/keys/#{key.id}") - response.status.should == 401 + expect(response.status).to eq(401) end end end diff --git a/spec/routing/admin_routing_spec.rb b/spec/routing/admin_routing_spec.rb index 7fe18ff47c3..bf8abcfb00f 100644 --- a/spec/routing/admin_routing_spec.rb +++ b/spec/routing/admin_routing_spec.rb @@ -12,47 +12,47 @@ require 'spec_helper' # DELETE /admin/users/:id(.:format) admin/users#destroy describe Admin::UsersController, "routing" do it "to #team_update" do - put("/admin/users/1/team_update").should route_to('admin/users#team_update', id: '1') + expect(put("/admin/users/1/team_update")).to route_to('admin/users#team_update', id: '1') end it "to #block" do - put("/admin/users/1/block").should route_to('admin/users#block', id: '1') + expect(put("/admin/users/1/block")).to route_to('admin/users#block', id: '1') end it "to #unblock" do - put("/admin/users/1/unblock").should route_to('admin/users#unblock', id: '1') + expect(put("/admin/users/1/unblock")).to route_to('admin/users#unblock', id: '1') end it "to #index" do - get("/admin/users").should route_to('admin/users#index') + expect(get("/admin/users")).to route_to('admin/users#index') end it "to #show" do - get("/admin/users/1").should route_to('admin/users#show', id: '1') + expect(get("/admin/users/1")).to route_to('admin/users#show', id: '1') end it "to #create" do - post("/admin/users").should route_to('admin/users#create') + expect(post("/admin/users")).to route_to('admin/users#create') end it "to #new" do - get("/admin/users/new").should route_to('admin/users#new') + expect(get("/admin/users/new")).to route_to('admin/users#new') end it "to #edit" do - get("/admin/users/1/edit").should route_to('admin/users#edit', id: '1') + expect(get("/admin/users/1/edit")).to route_to('admin/users#edit', id: '1') end it "to #show" do - get("/admin/users/1").should route_to('admin/users#show', id: '1') + expect(get("/admin/users/1")).to route_to('admin/users#show', id: '1') end it "to #update" do - put("/admin/users/1").should route_to('admin/users#update', id: '1') + expect(put("/admin/users/1")).to route_to('admin/users#update', id: '1') end it "to #destroy" do - delete("/admin/users/1").should route_to('admin/users#destroy', id: '1') + expect(delete("/admin/users/1")).to route_to('admin/users#destroy', id: '1') end end @@ -67,11 +67,11 @@ end # DELETE /admin/projects/:id(.:format) admin/projects#destroy {id: /[^\/]+/} describe Admin::ProjectsController, "routing" do it "to #index" do - get("/admin/projects").should route_to('admin/projects#index') + expect(get("/admin/projects")).to route_to('admin/projects#index') end it "to #show" do - get("/admin/projects/gitlab").should route_to('admin/projects#show', id: 'gitlab') + expect(get("/admin/projects/gitlab")).to route_to('admin/projects#show', namespace_id: 'gitlab') end end @@ -81,19 +81,19 @@ end # admin_hook DELETE /admin/hooks/:id(.:format) admin/hooks#destroy describe Admin::HooksController, "routing" do it "to #test" do - get("/admin/hooks/1/test").should route_to('admin/hooks#test', hook_id: '1') + expect(get("/admin/hooks/1/test")).to route_to('admin/hooks#test', hook_id: '1') end it "to #index" do - get("/admin/hooks").should route_to('admin/hooks#index') + expect(get("/admin/hooks")).to route_to('admin/hooks#index') end it "to #create" do - post("/admin/hooks").should route_to('admin/hooks#create') + expect(post("/admin/hooks")).to route_to('admin/hooks#create') end it "to #destroy" do - delete("/admin/hooks/1").should route_to('admin/hooks#destroy', id: '1') + expect(delete("/admin/hooks/1")).to route_to('admin/hooks#destroy', id: '1') end end @@ -101,21 +101,21 @@ end # admin_logs GET /admin/logs(.:format) admin/logs#show describe Admin::LogsController, "routing" do it "to #show" do - get("/admin/logs").should route_to('admin/logs#show') + expect(get("/admin/logs")).to route_to('admin/logs#show') end end # admin_background_jobs GET /admin/background_jobs(.:format) admin/background_jobs#show describe Admin::BackgroundJobsController, "routing" do it "to #show" do - get("/admin/background_jobs").should route_to('admin/background_jobs#show') + expect(get("/admin/background_jobs")).to route_to('admin/background_jobs#show') end end # admin_root /admin(.:format) admin/dashboard#index describe Admin::DashboardController, "routing" do it "to #index" do - get("/admin").should route_to('admin/dashboard#index') + expect(get("/admin")).to route_to('admin/dashboard#index') end end diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb index 112b825e023..24592942a96 100644 --- a/spec/routing/notifications_routing_spec.rb +++ b/spec/routing/notifications_routing_spec.rb @@ -3,11 +3,11 @@ require "spec_helper" describe Profiles::NotificationsController do describe "routing" do it "routes to #show" do - get("/profile/notifications").should route_to("profiles/notifications#show") + expect(get("/profile/notifications")).to route_to("profiles/notifications#show") end it "routes to #update" do - put("/profile/notifications").should route_to("profiles/notifications#update") + expect(put("/profile/notifications")).to route_to("profiles/notifications#update") end end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 4b2eb42c709..d9bd91f5990 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -12,86 +12,88 @@ require 'spec_helper' # Examples # # # Default behavior -# it_behaves_like "RESTful project resources" do +# it_behaves_like 'RESTful project resources' do # let(:controller) { 'issues' } # end # # # Customizing actions -# it_behaves_like "RESTful project resources" do +# it_behaves_like 'RESTful project resources' do # let(:actions) { [:index] } # let(:controller) { 'issues' } # end -shared_examples "RESTful project resources" do +shared_examples 'RESTful project resources' do let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] } - it "to #index" do - get("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#index", project_id: 'gitlab/gitlabhq') if actions.include?(:index) + it 'to #index' do + expect(get("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index) end - it "to #create" do - post("/gitlab/gitlabhq/#{controller}").should route_to("projects/#{controller}#create", project_id: 'gitlab/gitlabhq') if actions.include?(:create) + it 'to #create' do + expect(post("/gitlab/gitlabhq/#{controller}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create) end - it "to #new" do - get("/gitlab/gitlabhq/#{controller}/new").should route_to("projects/#{controller}#new", project_id: 'gitlab/gitlabhq') if actions.include?(:new) + it 'to #new' do + expect(get("/gitlab/gitlabhq/#{controller}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new) end - it "to #edit" do - get("/gitlab/gitlabhq/#{controller}/1/edit").should route_to("projects/#{controller}#edit", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:edit) + it 'to #edit' do + expect(get("/gitlab/gitlabhq/#{controller}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit) end - it "to #show" do - get("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#show", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:show) + it 'to #show' do + expect(get("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show) end - it "to #update" do - put("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#update", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:update) + it 'to #update' do + expect(put("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update) end - it "to #destroy" do - delete("/gitlab/gitlabhq/#{controller}/1").should route_to("projects/#{controller}#destroy", project_id: 'gitlab/gitlabhq', id: '1') if actions.include?(:destroy) + it 'to #destroy' do + expect(delete("/gitlab/gitlabhq/#{controller}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy) end end -# projects POST /projects(.:format) projects#create -# new_project GET /projects/new(.:format) projects#new -# fork_project POST /:id/fork(.:format) projects#fork -# files_project GET /:id/files(.:format) projects#files -# edit_project GET /:id/edit(.:format) projects#edit -# project GET /:id(.:format) projects#show -# PUT /:id(.:format) projects#update -# DELETE /:id(.:format) projects#destroy -describe ProjectsController, "routing" do - it "to #create" do - post("/projects").should route_to('projects#create') +# projects POST /projects(.:format) projects#create +# new_project GET /projects/new(.:format) projects#new +# files_project GET /:id/files(.:format) projects#files +# edit_project GET /:id/edit(.:format) projects#edit +# project GET /:id(.:format) projects#show +# PUT /:id(.:format) projects#update +# DELETE /:id(.:format) projects#destroy +# markdown_preview_project POST /:id/markdown_preview(.:format) projects#markdown_preview +describe ProjectsController, 'routing' do + it 'to #create' do + expect(post('/projects')).to route_to('projects#create') end - it "to #new" do - get("/projects/new").should route_to('projects#new') + it 'to #new' do + expect(get('/projects/new')).to route_to('projects#new') end - it "to #fork" do - post("/gitlab/gitlabhq/fork").should route_to('projects#fork', id: 'gitlab/gitlabhq') + it 'to #edit' do + expect(get('/gitlab/gitlabhq/edit')).to route_to('projects#edit', namespace_id: 'gitlab', id: 'gitlabhq') end - it "to #edit" do - get("/gitlab/gitlabhq/edit").should route_to('projects#edit', id: 'gitlab/gitlabhq') + it 'to #autocomplete_sources' do + expect(get('/gitlab/gitlabhq/autocomplete_sources')).to route_to('projects#autocomplete_sources', namespace_id: 'gitlab', id: 'gitlabhq') end - it "to #autocomplete_sources" do - get('/gitlab/gitlabhq/autocomplete_sources').should route_to('projects#autocomplete_sources', id: "gitlab/gitlabhq") + it 'to #show' do + expect(get('/gitlab/gitlabhq')).to route_to('projects#show', namespace_id: 'gitlab', id: 'gitlabhq') end - it "to #show" do - get("/gitlab/gitlabhq").should route_to('projects#show', id: 'gitlab/gitlabhq') + it 'to #update' do + expect(put('/gitlab/gitlabhq')).to route_to('projects#update', namespace_id: 'gitlab', id: 'gitlabhq') end - it "to #update" do - put("/gitlab/gitlabhq").should route_to('projects#update', id: 'gitlab/gitlabhq') + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq')).to route_to('projects#destroy', namespace_id: 'gitlab', id: 'gitlabhq') end - it "to #destroy" do - delete("/gitlab/gitlabhq").should route_to('projects#destroy', id: 'gitlab/gitlabhq') + it 'to #markdown_preview' do + expect(post('/gitlab/gitlabhq/markdown_preview')).to( + route_to('projects#markdown_preview', namespace_id: 'gitlab', id: 'gitlabhq') + ) end end @@ -101,16 +103,16 @@ end # edit_project_wiki GET /:project_id/wikis/:id/edit(.:format) projects/wikis#edit # project_wiki GET /:project_id/wikis/:id(.:format) projects/wikis#show # DELETE /:project_id/wikis/:id(.:format) projects/wikis#destroy -describe Projects::WikisController, "routing" do - it "to #pages" do - get("/gitlab/gitlabhq/wikis/pages").should route_to('projects/wikis#pages', project_id: 'gitlab/gitlabhq') +describe Projects::WikisController, 'routing' do + it 'to #pages' do + expect(get('/gitlab/gitlabhq/wikis/pages')).to route_to('projects/wikis#pages', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #history" do - get("/gitlab/gitlabhq/wikis/1/history").should route_to('projects/wikis#history', project_id: 'gitlab/gitlabhq', id: '1') + it 'to #history' do + expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it_behaves_like "RESTful project resources" do + it_behaves_like 'RESTful project resources' do let(:actions) { [:create, :edit, :show, :destroy] } let(:controller) { 'wikis' } end @@ -120,45 +122,45 @@ end # tags_project_repository GET /:project_id/repository/tags(.:format) projects/repositories#tags # archive_project_repository GET /:project_id/repository/archive(.:format) projects/repositories#archive # edit_project_repository GET /:project_id/repository/edit(.:format) projects/repositories#edit -describe Projects::RepositoriesController, "routing" do - it "to #archive" do - get("/gitlab/gitlabhq/repository/archive").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq') +describe Projects::RepositoriesController, 'routing' do + it 'to #archive' do + expect(get('/gitlab/gitlabhq/repository/archive')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #archive format:zip" do - get("/gitlab/gitlabhq/repository/archive.zip").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'zip') + it 'to #archive format:zip' do + expect(get('/gitlab/gitlabhq/repository/archive.zip')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'zip') end - it "to #archive format:tar.bz2" do - get("/gitlab/gitlabhq/repository/archive.tar.bz2").should route_to('projects/repositories#archive', project_id: 'gitlab/gitlabhq', format: 'tar.bz2') + it 'to #archive format:tar.bz2' do + expect(get('/gitlab/gitlabhq/repository/archive.tar.bz2')).to route_to('projects/repositories#archive', namespace_id: 'gitlab', project_id: 'gitlabhq', format: 'tar.bz2') end - it "to #show" do - get("/gitlab/gitlabhq/repository").should route_to('projects/repositories#show', project_id: 'gitlab/gitlabhq') + it 'to #show' do + expect(get('/gitlab/gitlabhq/repository')).to route_to('projects/repositories#show', namespace_id: 'gitlab', project_id: 'gitlabhq') end end -describe Projects::BranchesController, "routing" do - it "to #branches" do - get("/gitlab/gitlabhq/branches").should route_to('projects/branches#index', project_id: 'gitlab/gitlabhq') - delete("/gitlab/gitlabhq/branches/feature%2345").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45') - delete("/gitlab/gitlabhq/branches/feature%2B45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45') - delete("/gitlab/gitlabhq/branches/feature@45").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45') - delete("/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz') - delete("/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz') - delete("/gitlab/gitlabhq/branches/feature@45/foo/bar/baz").should route_to('projects/branches#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz') +describe Projects::BranchesController, 'routing' do + it 'to #branches' do + expect(get('/gitlab/gitlabhq/branches')).to route_to('projects/branches#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + expect(delete('/gitlab/gitlabhq/branches/feature%2345')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(delete('/gitlab/gitlabhq/branches/feature%2B45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(delete('/gitlab/gitlabhq/branches/feature@45')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(delete('/gitlab/gitlabhq/branches/feature%2345/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/branches/feature%2B45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/branches/feature@45/foo/bar/baz')).to route_to('projects/branches#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') end end -describe Projects::TagsController, "routing" do - it "to #tags" do - get("/gitlab/gitlabhq/tags").should route_to('projects/tags#index', project_id: 'gitlab/gitlabhq') - delete("/gitlab/gitlabhq/tags/feature%2345").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45') - delete("/gitlab/gitlabhq/tags/feature%2B45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45') - delete("/gitlab/gitlabhq/tags/feature@45").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45') - delete("/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature#45/foo/bar/baz') - delete("/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature+45/foo/bar/baz') - delete("/gitlab/gitlabhq/tags/feature@45/foo/bar/baz").should route_to('projects/tags#destroy', project_id: 'gitlab/gitlabhq', id: 'feature@45/foo/bar/baz') +describe Projects::TagsController, 'routing' do + it 'to #tags' do + expect(get('/gitlab/gitlabhq/tags')).to route_to('projects/tags#index', namespace_id: 'gitlab', project_id: 'gitlabhq') + expect(delete('/gitlab/gitlabhq/tags/feature%2345')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(delete('/gitlab/gitlabhq/tags/feature%2B45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(delete('/gitlab/gitlabhq/tags/feature@45')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(delete('/gitlab/gitlabhq/tags/feature%2345/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/tags/feature%2B45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45/foo/bar/baz') + expect(delete('/gitlab/gitlabhq/tags/feature@45/foo/bar/baz')).to route_to('projects/tags#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45/foo/bar/baz') end end @@ -170,8 +172,8 @@ end # project_deploy_key GET /:project_id/deploy_keys/:id(.:format) deploy_keys#show # PUT /:project_id/deploy_keys/:id(.:format) deploy_keys#update # DELETE /:project_id/deploy_keys/:id(.:format) deploy_keys#destroy -describe Projects::DeployKeysController, "routing" do - it_behaves_like "RESTful project resources" do +describe Projects::DeployKeysController, 'routing' do + it_behaves_like 'RESTful project resources' do let(:controller) { 'deploy_keys' } end end @@ -179,8 +181,8 @@ end # project_protected_branches GET /:project_id/protected_branches(.:format) protected_branches#index # POST /:project_id/protected_branches(.:format) protected_branches#create # project_protected_branch DELETE /:project_id/protected_branches/:id(.:format) protected_branches#destroy -describe Projects::ProtectedBranchesController, "routing" do - it_behaves_like "RESTful project resources" do +describe Projects::ProtectedBranchesController, 'routing' do + it_behaves_like 'RESTful project resources' do let(:actions) { [:index, :create, :destroy] } let(:controller) { 'protected_branches' } end @@ -189,21 +191,21 @@ end # switch_project_refs GET /:project_id/refs/switch(.:format) refs#switch # logs_tree_project_ref GET /:project_id/refs/:id/logs_tree(.:format) refs#logs_tree # logs_file_project_ref GET /:project_id/refs/:id/logs_tree/:path(.:format) refs#logs_tree -describe Projects::RefsController, "routing" do - it "to #switch" do - get("/gitlab/gitlabhq/refs/switch").should route_to('projects/refs#switch', project_id: 'gitlab/gitlabhq') - end - - it "to #logs_tree" do - get("/gitlab/gitlabhq/refs/stable/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable') - get("/gitlab/gitlabhq/refs/feature%2345/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45') - get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45') - get("/gitlab/gitlabhq/refs/feature@45/logs_tree").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45') - get("/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'foo/bar/baz') - get("/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature#45', path: 'foo/bar/baz') - get("/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature+45', path: 'foo/bar/baz') - get("/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'feature@45', path: 'foo/bar/baz') - get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('projects/refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss') +describe Projects::RefsController, 'routing' do + it 'to #switch' do + expect(get('/gitlab/gitlabhq/refs/switch')).to route_to('projects/refs#switch', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #logs_tree' do + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable') + expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45') + expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45') + expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45') + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45', path: 'foo/bar/baz') + expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/files.scss')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'files.scss') end end @@ -219,36 +221,36 @@ end # project_merge_request GET /:project_id/merge_requests/:id(.:format) projects/merge_requests#show # PUT /:project_id/merge_requests/:id(.:format) projects/merge_requests#update # DELETE /:project_id/merge_requests/:id(.:format) projects/merge_requests#destroy -describe Projects::MergeRequestsController, "routing" do - it "to #diffs" do - get("/gitlab/gitlabhq/merge_requests/1/diffs").should route_to('projects/merge_requests#diffs', project_id: 'gitlab/gitlabhq', id: '1') +describe Projects::MergeRequestsController, 'routing' do + it 'to #diffs' do + expect(get('/gitlab/gitlabhq/merge_requests/1/diffs')).to route_to('projects/merge_requests#diffs', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #automerge" do - post('/gitlab/gitlabhq/merge_requests/1/automerge').should route_to( + it 'to #automerge' do + expect(post('/gitlab/gitlabhq/merge_requests/1/automerge')).to route_to( 'projects/merge_requests#automerge', - project_id: 'gitlab/gitlabhq', id: '1' + namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1' ) end - it "to #automerge_check" do - get("/gitlab/gitlabhq/merge_requests/1/automerge_check").should route_to('projects/merge_requests#automerge_check', project_id: 'gitlab/gitlabhq', id: '1') + it 'to #automerge_check' do + expect(get('/gitlab/gitlabhq/merge_requests/1/automerge_check')).to route_to('projects/merge_requests#automerge_check', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #branch_from" do - get("/gitlab/gitlabhq/merge_requests/branch_from").should route_to('projects/merge_requests#branch_from', project_id: 'gitlab/gitlabhq') + it 'to #branch_from' do + expect(get('/gitlab/gitlabhq/merge_requests/branch_from')).to route_to('projects/merge_requests#branch_from', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #branch_to" do - get("/gitlab/gitlabhq/merge_requests/branch_to").should route_to('projects/merge_requests#branch_to', project_id: 'gitlab/gitlabhq') + it 'to #branch_to' do + expect(get('/gitlab/gitlabhq/merge_requests/branch_to')).to route_to('projects/merge_requests#branch_to', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #show" do - get("/gitlab/gitlabhq/merge_requests/1.diff").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'diff') - get("/gitlab/gitlabhq/merge_requests/1.patch").should route_to('projects/merge_requests#show', project_id: 'gitlab/gitlabhq', id: '1', format: 'patch') + it 'to #show' do + expect(get('/gitlab/gitlabhq/merge_requests/1.diff')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'diff') + expect(get('/gitlab/gitlabhq/merge_requests/1.patch')).to route_to('projects/merge_requests#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: 'patch') end - it_behaves_like "RESTful project resources" do + it_behaves_like 'RESTful project resources' do let(:controller) { 'merge_requests' } let(:actions) { [:index, :create, :new, :edit, :show, :update] } end @@ -262,37 +264,37 @@ end # project_snippet GET /:project_id/snippets/:id(.:format) snippets#show # PUT /:project_id/snippets/:id(.:format) snippets#update # DELETE /:project_id/snippets/:id(.:format) snippets#destroy -describe SnippetsController, "routing" do - it "to #raw" do - get("/gitlab/gitlabhq/snippets/1/raw").should route_to('projects/snippets#raw', project_id: 'gitlab/gitlabhq', id: '1') +describe SnippetsController, 'routing' do + it 'to #raw' do + expect(get('/gitlab/gitlabhq/snippets/1/raw')).to route_to('projects/snippets#raw', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #index" do - get("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#index", project_id: 'gitlab/gitlabhq') + it 'to #index' do + expect(get('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#index', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #create" do - post("/gitlab/gitlabhq/snippets").should route_to("projects/snippets#create", project_id: 'gitlab/gitlabhq') + it 'to #create' do + expect(post('/gitlab/gitlabhq/snippets')).to route_to('projects/snippets#create', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #new" do - get("/gitlab/gitlabhq/snippets/new").should route_to("projects/snippets#new", project_id: 'gitlab/gitlabhq') + it 'to #new' do + expect(get('/gitlab/gitlabhq/snippets/new')).to route_to('projects/snippets#new', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #edit" do - get("/gitlab/gitlabhq/snippets/1/edit").should route_to("projects/snippets#edit", project_id: 'gitlab/gitlabhq', id: '1') + it 'to #edit' do + expect(get('/gitlab/gitlabhq/snippets/1/edit')).to route_to('projects/snippets#edit', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #show" do - get("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#show", project_id: 'gitlab/gitlabhq', id: '1') + it 'to #show' do + expect(get('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #update" do - put("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#update", project_id: 'gitlab/gitlabhq', id: '1') + it 'to #update' do + expect(put('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#update', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it "to #destroy" do - delete("/gitlab/gitlabhq/snippets/1").should route_to("projects/snippets#destroy", project_id: 'gitlab/gitlabhq', id: '1') + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq/snippets/1')).to route_to('projects/snippets#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end end @@ -300,24 +302,24 @@ end # project_hooks GET /:project_id/hooks(.:format) hooks#index # POST /:project_id/hooks(.:format) hooks#create # project_hook DELETE /:project_id/hooks/:id(.:format) hooks#destroy -describe Projects::HooksController, "routing" do - it "to #test" do - get("/gitlab/gitlabhq/hooks/1/test").should route_to('projects/hooks#test', project_id: 'gitlab/gitlabhq', id: '1') +describe Projects::HooksController, 'routing' do + it 'to #test' do + expect(get('/gitlab/gitlabhq/hooks/1/test')).to route_to('projects/hooks#test', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') end - it_behaves_like "RESTful project resources" do + it_behaves_like 'RESTful project resources' do let(:actions) { [:index, :create, :destroy] } let(:controller) { 'hooks' } end end # project_commit GET /:project_id/commit/:id(.:format) commit#show {id: /[[:alnum:]]{6,40}/, project_id: /[^\/]+/} -describe Projects::CommitController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/commit/4246fb").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb') - get("/gitlab/gitlabhq/commit/4246fb.diff").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'diff') - get("/gitlab/gitlabhq/commit/4246fb.patch").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fb', format: 'patch') - get("/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5").should route_to('projects/commit#show', project_id: 'gitlab/gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') +describe Projects::CommitController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/commit/4246fb')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb') + expect(get('/gitlab/gitlabhq/commit/4246fb.diff')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb', format: 'diff') + expect(get('/gitlab/gitlabhq/commit/4246fb.patch')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fb', format: 'patch') + expect(get('/gitlab/gitlabhq/commit/4246fbd13872934f72a8fd0d6fb1317b47b59cb5')).to route_to('projects/commit#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '4246fbd13872934f72a8fd0d6fb1317b47b59cb5') end end @@ -325,28 +327,25 @@ end # project_commits GET /:project_id/commits(.:format) commits#index # POST /:project_id/commits(.:format) commits#create # project_commit GET /:project_id/commits/:id(.:format) commits#show -describe Projects::CommitsController, "routing" do - it_behaves_like "RESTful project resources" do +describe Projects::CommitsController, 'routing' do + it_behaves_like 'RESTful project resources' do let(:actions) { [:show] } let(:controller) { 'commits' } end - it "to #show" do - get("/gitlab/gitlabhq/commits/master.atom").should route_to('projects/commits#show', project_id: 'gitlab/gitlabhq', id: "master", format: "atom") + it 'to #show' do + expect(get('/gitlab/gitlabhq/commits/master.atom')).to route_to('projects/commits#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'atom') end end -# project_team_members GET /:project_id/team_members(.:format) team_members#index -# POST /:project_id/team_members(.:format) team_members#create -# new_project_team_member GET /:project_id/team_members/new(.:format) team_members#new -# edit_project_team_member GET /:project_id/team_members/:id/edit(.:format) team_members#edit -# project_team_member GET /:project_id/team_members/:id(.:format) team_members#show -# PUT /:project_id/team_members/:id(.:format) team_members#update -# DELETE /:project_id/team_members/:id(.:format) team_members#destroy -describe Projects::TeamMembersController, "routing" do - it_behaves_like "RESTful project resources" do - let(:actions) { [:new, :create, :update, :destroy] } - let(:controller) { 'team_members' } +# project_project_members GET /:project_id/project_members(.:format) project_members#index +# POST /:project_id/project_members(.:format) project_members#create +# PUT /:project_id/project_members/:id(.:format) project_members#update +# DELETE /:project_id/project_members/:id(.:format) project_members#destroy +describe Projects::ProjectMembersController, 'routing' do + it_behaves_like 'RESTful project resources' do + let(:actions) { [:index, :create, :update, :destroy] } + let(:controller) { 'project_members' } end end @@ -357,17 +356,17 @@ end # project_milestone GET /:project_id/milestones/:id(.:format) milestones#show # PUT /:project_id/milestones/:id(.:format) milestones#update # DELETE /:project_id/milestones/:id(.:format) milestones#destroy -describe Projects::MilestonesController, "routing" do - it_behaves_like "RESTful project resources" do +describe Projects::MilestonesController, 'routing' do + it_behaves_like 'RESTful project resources' do let(:controller) { 'milestones' } let(:actions) { [:index, :create, :new, :edit, :show, :update] } end end # project_labels GET /:project_id/labels(.:format) labels#index -describe Projects::LabelsController, "routing" do - it "to #index" do - get("/gitlab/gitlabhq/labels").should route_to('projects/labels#index', project_id: 'gitlab/gitlabhq') +describe Projects::LabelsController, 'routing' do + it 'to #index' do + expect(get('/gitlab/gitlabhq/labels')).to route_to('projects/labels#index', namespace_id: 'gitlab', project_id: 'gitlabhq') end end @@ -381,84 +380,114 @@ end # project_issue GET /:project_id/issues/:id(.:format) issues#show # PUT /:project_id/issues/:id(.:format) issues#update # DELETE /:project_id/issues/:id(.:format) issues#destroy -describe Projects::IssuesController, "routing" do - it "to #bulk_update" do - post("/gitlab/gitlabhq/issues/bulk_update").should route_to('projects/issues#bulk_update', project_id: 'gitlab/gitlabhq') +describe Projects::IssuesController, 'routing' do + it 'to #bulk_update' do + expect(post('/gitlab/gitlabhq/issues/bulk_update')).to route_to('projects/issues#bulk_update', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it_behaves_like "RESTful project resources" do + it_behaves_like 'RESTful project resources' do let(:controller) { 'issues' } let(:actions) { [:index, :create, :new, :edit, :show, :update] } end end -# preview_project_notes POST /:project_id/notes/preview(.:format) notes#preview # project_notes GET /:project_id/notes(.:format) notes#index # POST /:project_id/notes(.:format) notes#create # project_note DELETE /:project_id/notes/:id(.:format) notes#destroy -describe Projects::NotesController, "routing" do - it "to #preview" do - post("/gitlab/gitlabhq/notes/preview").should route_to('projects/notes#preview', project_id: 'gitlab/gitlabhq') - end - - it_behaves_like "RESTful project resources" do +describe Projects::NotesController, 'routing' do + it_behaves_like 'RESTful project resources' do let(:actions) { [:index, :create, :destroy] } let(:controller) { 'notes' } end end # project_blame GET /:project_id/blame/:id(.:format) blame#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::BlameController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/blame/master/app/models/project.rb").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb') - get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('projects/blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss') +describe Projects::BlameController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/blame/master/app/models/project.rb')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/blame/master/files.scss')).to route_to('projects/blame#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') end end # project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::BlobController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/blob/master/app/models/project.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb') - get("/gitlab/gitlabhq/blob/master/app/models/compare.rb").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/compare.rb') - get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('projects/blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss') +describe Projects::BlobController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/blob/master/app/models/compare.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/compare.rb') + expect(get('/gitlab/gitlabhq/blob/master/app/models/diff.js')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/diff.js') + expect(get('/gitlab/gitlabhq/blob/master/files.scss')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') end end # project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /.+/, project_id: /[^\/]+/} -describe Projects::TreeController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/tree/master/app/models/project.rb").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/app/models/project.rb') - get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('projects/tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss') +describe Projects::TreeController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') + expect(get('/gitlab/gitlabhq/tree/master/files.scss')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/files.scss') + end +end + +describe Projects::BlobController, 'routing' do + it 'to #edit' do + expect(get('/gitlab/gitlabhq/edit/master/app/models/project.rb')).to( + route_to('projects/blob#edit', + namespace_id: 'gitlab', project_id: 'gitlabhq', + id: 'master/app/models/project.rb')) + end + + it 'to #preview' do + expect(post('/gitlab/gitlabhq/preview/master/app/models/project.rb')).to( + route_to('projects/blob#preview', + namespace_id: 'gitlab', project_id: 'gitlabhq', + id: 'master/app/models/project.rb')) end end # project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/} # POST /:project_id/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/} # project_compare /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/} -describe Projects::CompareController, "routing" do - it "to #index" do - get("/gitlab/gitlabhq/compare").should route_to('projects/compare#index', project_id: 'gitlab/gitlabhq') +describe Projects::CompareController, 'routing' do + it 'to #index' do + expect(get('/gitlab/gitlabhq/compare')).to route_to('projects/compare#index', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #compare" do - post("/gitlab/gitlabhq/compare").should route_to('projects/compare#create', project_id: 'gitlab/gitlabhq') + it 'to #compare' do + expect(post('/gitlab/gitlabhq/compare')).to route_to('projects/compare#create', namespace_id: 'gitlab', project_id: 'gitlabhq') end - it "to #show" do - get("/gitlab/gitlabhq/compare/master...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'master', to: 'stable') - get("/gitlab/gitlabhq/compare/issue/1234...stable").should route_to('projects/compare#show', project_id: 'gitlab/gitlabhq', from: 'issue/1234', to: 'stable') + it 'to #show' do + expect(get('/gitlab/gitlabhq/compare/master...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'master', to: 'stable') + expect(get('/gitlab/gitlabhq/compare/issue/1234...stable')).to route_to('projects/compare#show', namespace_id: 'gitlab', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable') end end -describe Projects::NetworkController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/network/master").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master') - get("/gitlab/gitlabhq/network/master.json").should route_to('projects/network#show', project_id: 'gitlab/gitlabhq', id: 'master', format: "json") +describe Projects::NetworkController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/network/master')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') + expect(get('/gitlab/gitlabhq/network/master.json')).to route_to('projects/network#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master', format: 'json') + end +end + +describe Projects::GraphsController, 'routing' do + it 'to #show' do + expect(get('/gitlab/gitlabhq/graphs/master')).to route_to('projects/graphs#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') + end +end + +describe Projects::ForksController, 'routing' do + it 'to #new' do + expect(get('/gitlab/gitlabhq/fork/new')).to route_to('projects/forks#new', namespace_id: 'gitlab', project_id: 'gitlabhq') + end + + it 'to #create' do + expect(post('/gitlab/gitlabhq/fork')).to route_to('projects/forks#create', namespace_id: 'gitlab', project_id: 'gitlabhq') end end -describe Projects::GraphsController, "routing" do - it "to #show" do - get("/gitlab/gitlabhq/graphs/master").should route_to('projects/graphs#show', project_id: 'gitlab/gitlabhq', id: 'master') +# project_avatar DELETE /project/avatar(.:format) projects/avatars#destroy +describe Projects::AvatarsController, 'routing' do + it 'to #destroy' do + expect(delete('/gitlab/gitlabhq/avatar')).to route_to( + 'projects/avatars#destroy', namespace_id: 'gitlab', project_id: 'gitlabhq') end end diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb index 1e92cf62dd5..d4915b51952 100644 --- a/spec/routing/routing_spec.rb +++ b/spec/routing/routing_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' # search GET /search(.:format) search#show describe SearchController, "routing" do it "to #show" do - get("/search").should route_to('search#show') + expect(get("/search")).to route_to('search#show') end end @@ -11,11 +11,11 @@ end # /:path Grack describe "Mounted Apps", "routing" do it "to API" do - get("/api/issues").should be_routable + expect(get("/api/issues")).to be_routable end it "to Grack" do - get("/gitlab/gitlabhq.git").should be_routable + expect(get("/gitlab/gitlabhq.git")).to be_routable end end @@ -28,39 +28,39 @@ end # DELETE /snippets/:id(.:format) snippets#destroy describe SnippetsController, "routing" do it "to #user_index" do - get("/s/User").should route_to('snippets#user_index', username: 'User') + expect(get("/s/User")).to route_to('snippets#user_index', username: 'User') end it "to #raw" do - get("/snippets/1/raw").should route_to('snippets#raw', id: '1') + expect(get("/snippets/1/raw")).to route_to('snippets#raw', id: '1') end it "to #index" do - get("/snippets").should route_to('snippets#index') + expect(get("/snippets")).to route_to('snippets#index') end it "to #create" do - post("/snippets").should route_to('snippets#create') + expect(post("/snippets")).to route_to('snippets#create') end it "to #new" do - get("/snippets/new").should route_to('snippets#new') + expect(get("/snippets/new")).to route_to('snippets#new') end it "to #edit" do - get("/snippets/1/edit").should route_to('snippets#edit', id: '1') + expect(get("/snippets/1/edit")).to route_to('snippets#edit', id: '1') end it "to #show" do - get("/snippets/1").should route_to('snippets#show', id: '1') + expect(get("/snippets/1")).to route_to('snippets#show', id: '1') end it "to #update" do - put("/snippets/1").should route_to('snippets#update', id: '1') + expect(put("/snippets/1")).to route_to('snippets#update', id: '1') end it "to #destroy" do - delete("/snippets/1").should route_to('snippets#destroy', id: '1') + expect(delete("/snippets/1")).to route_to('snippets#destroy', id: '1') end end @@ -75,39 +75,39 @@ end # help_raketasks GET /help/raketasks(.:format) help#raketasks describe HelpController, "routing" do it "to #index" do - get("/help").should route_to('help#index') + expect(get("/help")).to route_to('help#index') end it "to #permissions" do - get("/help/permissions/permissions").should route_to('help#show', category: "permissions", file: "permissions") + expect(get("/help/permissions/permissions")).to route_to('help#show', category: "permissions", file: "permissions") end it "to #workflow" do - get("/help/workflow/README").should route_to('help#show', category: "workflow", file: "README") + expect(get("/help/workflow/README")).to route_to('help#show', category: "workflow", file: "README") end it "to #api" do - get("/help/api/README").should route_to('help#show', category: "api", file: "README") + expect(get("/help/api/README")).to route_to('help#show', category: "api", file: "README") end it "to #web_hooks" do - get("/help/web_hooks/web_hooks").should route_to('help#show', category: "web_hooks", file: "web_hooks") + expect(get("/help/web_hooks/web_hooks")).to route_to('help#show', category: "web_hooks", file: "web_hooks") end it "to #system_hooks" do - get("/help/system_hooks/system_hooks").should route_to('help#show', category: "system_hooks", file: "system_hooks") + expect(get("/help/system_hooks/system_hooks")).to route_to('help#show', category: "system_hooks", file: "system_hooks") end it "to #markdown" do - get("/help/markdown/markdown").should route_to('help#show',category: "markdown", file: "markdown") + expect(get("/help/markdown/markdown")).to route_to('help#show',category: "markdown", file: "markdown") end it "to #ssh" do - get("/help/ssh/README").should route_to('help#show', category: "ssh", file: "README") + expect(get("/help/ssh/README")).to route_to('help#show', category: "ssh", file: "README") end it "to #raketasks" do - get("/help/raketasks/README").should route_to('help#show', category: "raketasks", file: "README") + expect(get("/help/raketasks/README")).to route_to('help#show', category: "raketasks", file: "README") end end @@ -121,23 +121,23 @@ end # profile_update PUT /profile/update(.:format) profile#update describe ProfilesController, "routing" do it "to #account" do - get("/profile/account").should route_to('profiles/accounts#show') + expect(get("/profile/account")).to route_to('profiles/accounts#show') end it "to #history" do - get("/profile/history").should route_to('profiles#history') + expect(get("/profile/history")).to route_to('profiles#history') end it "to #reset_private_token" do - put("/profile/reset_private_token").should route_to('profiles#reset_private_token') + expect(put("/profile/reset_private_token")).to route_to('profiles#reset_private_token') end it "to #show" do - get("/profile").should route_to('profiles#show') + expect(get("/profile")).to route_to('profiles#show') end it "to #design" do - get("/profile/design").should route_to('profiles#design') + expect(get("/profile/design")).to route_to('profiles#design') end end @@ -150,36 +150,36 @@ end # DELETE /keys/:id(.:format) keys#destroy describe Profiles::KeysController, "routing" do it "to #index" do - get("/profile/keys").should route_to('profiles/keys#index') + expect(get("/profile/keys")).to route_to('profiles/keys#index') end it "to #create" do - post("/profile/keys").should route_to('profiles/keys#create') + expect(post("/profile/keys")).to route_to('profiles/keys#create') end it "to #new" do - get("/profile/keys/new").should route_to('profiles/keys#new') + expect(get("/profile/keys/new")).to route_to('profiles/keys#new') end it "to #edit" do - get("/profile/keys/1/edit").should route_to('profiles/keys#edit', id: '1') + expect(get("/profile/keys/1/edit")).to route_to('profiles/keys#edit', id: '1') end it "to #show" do - get("/profile/keys/1").should route_to('profiles/keys#show', id: '1') + expect(get("/profile/keys/1")).to route_to('profiles/keys#show', id: '1') end it "to #update" do - put("/profile/keys/1").should route_to('profiles/keys#update', id: '1') + expect(put("/profile/keys/1")).to route_to('profiles/keys#update', id: '1') end it "to #destroy" do - delete("/profile/keys/1").should route_to('profiles/keys#destroy', id: '1') + expect(delete("/profile/keys/1")).to route_to('profiles/keys#destroy', id: '1') end # get all the ssh-keys of a user it "to #get_keys" do - get("/foo.keys").should route_to('profiles/keys#get_keys', username: 'foo') + expect(get("/foo.keys")).to route_to('profiles/keys#get_keys', username: 'foo') end end @@ -188,22 +188,22 @@ end # DELETE /keys/:id(.:format) keys#destroy describe Profiles::EmailsController, "routing" do it "to #index" do - get("/profile/emails").should route_to('profiles/emails#index') + expect(get("/profile/emails")).to route_to('profiles/emails#index') end it "to #create" do - post("/profile/emails").should route_to('profiles/emails#create') + expect(post("/profile/emails")).to route_to('profiles/emails#create') end it "to #destroy" do - delete("/profile/emails/1").should route_to('profiles/emails#destroy', id: '1') + expect(delete("/profile/emails/1")).to route_to('profiles/emails#destroy', id: '1') end end # profile_avatar DELETE /profile/avatar(.:format) profiles/avatars#destroy describe Profiles::AvatarsController, "routing" do it "to #destroy" do - delete("/profile/avatar").should route_to('profiles/avatars#destroy') + expect(delete("/profile/avatar")).to route_to('profiles/avatars#destroy') end end @@ -213,16 +213,16 @@ end # root / dashboard#show describe DashboardController, "routing" do it "to #index" do - get("/dashboard").should route_to('dashboard#show') - get("/").should route_to('dashboard#show') + expect(get("/dashboard")).to route_to('dashboard#show') + expect(get("/")).to route_to('dashboard#show') end it "to #issues" do - get("/dashboard/issues").should route_to('dashboard#issues') + expect(get("/dashboard/issues")).to route_to('dashboard#issues') end it "to #merge_requests" do - get("/dashboard/merge_requests").should route_to('dashboard#merge_requests') + expect(get("/dashboard/merge_requests")).to route_to('dashboard#merge_requests') end end @@ -241,11 +241,11 @@ end describe "Groups", "routing" do it "to #show" do - get("/groups/1").should route_to('groups#show', id: '1') + expect(get("/groups/1")).to route_to('groups#show', id: '1') end it "also display group#show on the short path" do - get('/1').should route_to('namespaces#show', id: '1') + expect(get('/1')).to route_to('namespaces#show', id: '1') end end diff --git a/spec/services/create_snippet_service_spec.rb b/spec/services/create_snippet_service_spec.rb new file mode 100644 index 00000000000..08689c15ca8 --- /dev/null +++ b/spec/services/create_snippet_service_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe CreateSnippetService do + before do + @user = create :user + @admin = create :user, admin: true + @opts = { + title: 'Test snippet', + file_name: 'snippet.rb', + content: 'puts "hello world"', + visibility_level: Gitlab::VisibilityLevel::PRIVATE + } + end + + context 'When public visibility is restricted' do + before do + allow_any_instance_of(ApplicationSetting).to( + receive(:restricted_visibility_levels).and_return( + [Gitlab::VisibilityLevel::PUBLIC] + ) + ) + + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end + + it 'non-admins should not be able to create a public snippet' do + snippet = create_snippet(nil, @user, @opts) + expect(snippet.errors.messages).to have_key(:visibility_level) + expect(snippet.errors.messages[:visibility_level].first).to( + match('Public visibility has been restricted') + ) + end + + it 'admins should be able to create a public snippet' do + snippet = create_snippet(nil, @admin, @opts) + expect(snippet.errors.any?).to be_falsey + expect(snippet.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC) + end + end + + def create_snippet(project, user, opts) + CreateSnippetService.new(project, user, opts).execute + end +end diff --git a/spec/services/event_create_service_spec.rb b/spec/services/event_create_service_spec.rb index 713aa3e7e74..007a9eed192 100644 --- a/spec/services/event_create_service_spec.rb +++ b/spec/services/event_create_service_spec.rb @@ -7,7 +7,7 @@ describe EventCreateService do describe :open_issue do let(:issue) { create(:issue) } - it { service.open_issue(issue, issue.author).should be_true } + it { expect(service.open_issue(issue, issue.author)).to be_truthy } it "should create new event" do expect { service.open_issue(issue, issue.author) }.to change { Event.count } @@ -17,7 +17,7 @@ describe EventCreateService do describe :close_issue do let(:issue) { create(:issue) } - it { service.close_issue(issue, issue.author).should be_true } + it { expect(service.close_issue(issue, issue.author)).to be_truthy } it "should create new event" do expect { service.close_issue(issue, issue.author) }.to change { Event.count } @@ -27,7 +27,7 @@ describe EventCreateService do describe :reopen_issue do let(:issue) { create(:issue) } - it { service.reopen_issue(issue, issue.author).should be_true } + it { expect(service.reopen_issue(issue, issue.author)).to be_truthy } it "should create new event" do expect { service.reopen_issue(issue, issue.author) }.to change { Event.count } @@ -39,7 +39,7 @@ describe EventCreateService do describe :open_mr do let(:merge_request) { create(:merge_request) } - it { service.open_mr(merge_request, merge_request.author).should be_true } + it { expect(service.open_mr(merge_request, merge_request.author)).to be_truthy } it "should create new event" do expect { service.open_mr(merge_request, merge_request.author) }.to change { Event.count } @@ -49,7 +49,7 @@ describe EventCreateService do describe :close_mr do let(:merge_request) { create(:merge_request) } - it { service.close_mr(merge_request, merge_request.author).should be_true } + it { expect(service.close_mr(merge_request, merge_request.author)).to be_truthy } it "should create new event" do expect { service.close_mr(merge_request, merge_request.author) }.to change { Event.count } @@ -59,7 +59,7 @@ describe EventCreateService do describe :merge_mr do let(:merge_request) { create(:merge_request) } - it { service.merge_mr(merge_request, merge_request.author).should be_true } + it { expect(service.merge_mr(merge_request, merge_request.author)).to be_truthy } it "should create new event" do expect { service.merge_mr(merge_request, merge_request.author) }.to change { Event.count } @@ -69,7 +69,7 @@ describe EventCreateService do describe :reopen_mr do let(:merge_request) { create(:merge_request) } - it { service.reopen_mr(merge_request, merge_request.author).should be_true } + it { expect(service.reopen_mr(merge_request, merge_request.author)).to be_truthy } it "should create new event" do expect { service.reopen_mr(merge_request, merge_request.author) }.to change { Event.count } @@ -83,7 +83,7 @@ describe EventCreateService do describe :open_milestone do let(:milestone) { create(:milestone) } - it { service.open_milestone(milestone, user).should be_true } + it { expect(service.open_milestone(milestone, user)).to be_truthy } it "should create new event" do expect { service.open_milestone(milestone, user) }.to change { Event.count } @@ -93,7 +93,7 @@ describe EventCreateService do describe :close_mr do let(:milestone) { create(:milestone) } - it { service.close_milestone(milestone, user).should be_true } + it { expect(service.close_milestone(milestone, user)).to be_truthy } it "should create new event" do expect { service.close_milestone(milestone, user) }.to change { Event.count } diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb index 4ef053a767f..1b1e3ca5f8b 100644 --- a/spec/services/git_push_service_spec.rb +++ b/spec/services/git_push_service_spec.rb @@ -8,7 +8,7 @@ describe GitPushService do let (:service) { GitPushService.new } before do - @blankrev = '0000000000000000000000000000000000000000' + @blankrev = Gitlab::Git::BLANK_SHA @oldrev = sample_commit.parent_id @newrev = sample_commit.id @ref = 'refs/heads/master' @@ -20,7 +20,7 @@ describe GitPushService do service.execute(project, user, @blankrev, @newrev, @ref) end - it { should be_true } + it { is_expected.to be_truthy } end context 'existing branch' do @@ -28,7 +28,7 @@ describe GitPushService do service.execute(project, user, @oldrev, @newrev, @ref) end - it { should be_true } + it { is_expected.to be_truthy } end context 'rm branch' do @@ -36,7 +36,7 @@ describe GitPushService do service.execute(project, user, @oldrev, @blankrev, @ref) end - it { should be_true } + it { is_expected.to be_truthy } end end @@ -49,41 +49,54 @@ describe GitPushService do subject { @push_data } - it { should include(before: @oldrev) } - it { should include(after: @newrev) } - it { should include(ref: @ref) } - it { should include(user_id: user.id) } - it { should include(user_name: user.name) } - it { should include(project_id: project.id) } + it { is_expected.to include(object_kind: 'push') } + it { is_expected.to include(before: @oldrev) } + it { is_expected.to include(after: @newrev) } + it { is_expected.to include(ref: @ref) } + it { is_expected.to include(user_id: user.id) } + it { is_expected.to include(user_name: user.name) } + it { is_expected.to include(project_id: project.id) } context "with repository data" do subject { @push_data[:repository] } - it { should include(name: project.name) } - it { should include(url: project.url_to_repo) } - it { should include(description: project.description) } - it { should include(homepage: project.web_url) } + it { is_expected.to include(name: project.name) } + it { is_expected.to include(url: project.url_to_repo) } + it { is_expected.to include(description: project.description) } + it { is_expected.to include(homepage: project.web_url) } end context "with commits" do subject { @push_data[:commits] } - it { should be_an(Array) } - it { should have(1).element } + it { is_expected.to be_an(Array) } + it 'has 1 element' do + expect(subject.size).to eq(1) + end context "the commit" do subject { @push_data[:commits].first } - it { should include(id: @commit.id) } - it { should include(message: @commit.safe_message) } - it { should include(timestamp: @commit.date.xmlschema) } - it { should include(url: "#{Gitlab.config.gitlab.url}/#{project.to_param}/commit/#{@commit.id}") } + it { is_expected.to include(id: @commit.id) } + it { is_expected.to include(message: @commit.safe_message) } + it { is_expected.to include(timestamp: @commit.date.xmlschema) } + it do + is_expected.to include( + url: [ + Gitlab.config.gitlab.url, + project.namespace.to_param, + project.to_param, + 'commit', + @commit.id + ].join('/') + ) + end context "with a author" do subject { @push_data[:commits].first[:author] } - it { should include(name: @commit.author_name) } - it { should include(email: @commit.author_email) } + it { is_expected.to include(name: @commit.author_name) } + it { is_expected.to include(email: @commit.author_email) } end end end @@ -95,28 +108,46 @@ describe GitPushService do @event = Event.last end - it { @event.should_not be_nil } - it { @event.project.should == project } - it { @event.action.should == Event::PUSHED } - it { @event.data.should == service.push_data } + it { expect(@event).not_to be_nil } + it { expect(@event.project).to eq(project) } + it { expect(@event.action).to eq(Event::PUSHED) } + it { expect(@event.data).to eq(service.push_data) } end describe "Web Hooks" do context "execute web hooks" do it "when pushing a branch for the first time" do - project.should_receive(:execute_hooks) - project.default_branch.should == "master" - project.protected_branches.should_receive(:create).with({ name: "master" }) + expect(project).to receive(:execute_hooks) + expect(project.default_branch).to eq("master") + expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: false }) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection disabled" do + ApplicationSetting.any_instance.stub(default_branch_protection: 0) + + expect(project).to receive(:execute_hooks) + expect(project.default_branch).to eq("master") + expect(project.protected_branches).not_to receive(:create) + service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') + end + + it "when pushing a branch for the first time with default branch protection set to 'developers can push'" do + ApplicationSetting.any_instance.stub(default_branch_protection: 1) + + expect(project).to receive(:execute_hooks) + expect(project.default_branch).to eq("master") + expect(project.protected_branches).to receive(:create).with({ name: "master", developers_can_push: true }) service.execute(project, user, @blankrev, 'newrev', 'refs/heads/master') end it "when pushing new commits to existing branch" do - project.should_receive(:execute_hooks) + expect(project).to receive(:execute_hooks) service.execute(project, user, 'oldrev', 'newrev', 'refs/heads/master') end it "when pushing tags" do - project.should_not_receive(:execute_hooks) + expect(project).not_to receive(:execute_hooks) service.execute(project, user, 'newrev', 'newrev', 'refs/tags/v1.0.0') end end @@ -138,7 +169,7 @@ describe GitPushService do end it "creates a note if a pushed commit mentions an issue" do - Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + expect(Note).to receive(:create_cross_reference_note).with(issue, commit, commit_author, project) service.execute(project, user, @oldrev, @newrev, @ref) end @@ -146,35 +177,26 @@ describe GitPushService do it "only creates a cross-reference note if one doesn't already exist" do Note.create_cross_reference_note(issue, commit, user, project) - Note.should_not_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + expect(Note).not_to receive(:create_cross_reference_note).with(issue, commit, commit_author, project) service.execute(project, user, @oldrev, @newrev, @ref) end it "defaults to the pushing user if the commit's author is not known" do commit.stub(author_name: 'unknown name', author_email: 'unknown@email.com') - Note.should_receive(:create_cross_reference_note).with(issue, commit, user, project) + expect(Note).to receive(:create_cross_reference_note).with(issue, commit, user, project) service.execute(project, user, @oldrev, @newrev, @ref) end it "finds references in the first push to a non-default branch" do - project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([]) - project.repository.stub(:commits_between).with("master", @newrev).and_return([commit]) + allow(project.repository).to receive(:commits_between).with(@blankrev, @newrev).and_return([]) + allow(project.repository).to receive(:commits_between).with("master", @newrev).and_return([commit]) - Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) + expect(Note).to receive(:create_cross_reference_note).with(issue, commit, commit_author, project) service.execute(project, user, @blankrev, @newrev, 'refs/heads/other') end - - it "finds references in the first push to a default branch" do - project.repository.stub(:commits_between).with(@blankrev, @newrev).and_return([]) - project.repository.stub(:commits).with(@newrev).and_return([commit]) - - Note.should_receive(:create_cross_reference_note).with(issue, commit, commit_author, project) - - service.execute(project, user, @blankrev, @newrev, 'refs/heads/master') - end end describe "closing issues from pushed commits" do @@ -197,7 +219,7 @@ describe GitPushService do it "closes issues with commit messages" do service.execute(project, user, @oldrev, @newrev, @ref) - Issue.find(issue.id).should be_closed + expect(Issue.find(issue.id)).to be_closed end it "doesn't create cross-reference notes for a closing reference" do @@ -214,7 +236,7 @@ describe GitPushService do service.execute(project, user, @oldrev, @newrev, 'refs/heads/hurf') }.not_to change { Note.where(project_id: project.id, system: true).count } - Issue.find(issue.id).should be_opened + expect(Issue.find(issue.id)).to be_opened end end end diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb index e65a8204c54..fcf462edbfc 100644 --- a/spec/services/git_tag_push_service_spec.rb +++ b/spec/services/git_tag_push_service_spec.rb @@ -19,27 +19,27 @@ describe GitTagPushService do subject { @push_data } - it { should include(ref: @ref) } - it { should include(before: @oldrev) } - it { should include(after: @newrev) } - it { should include(user_id: user.id) } - it { should include(user_name: user.name) } - it { should include(project_id: project.id) } + it { is_expected.to include(ref: @ref) } + it { is_expected.to include(before: @oldrev) } + it { is_expected.to include(after: @newrev) } + it { is_expected.to include(user_id: user.id) } + it { is_expected.to include(user_name: user.name) } + it { is_expected.to include(project_id: project.id) } context 'With repository data' do subject { @push_data[:repository] } - it { should include(name: project.name) } - it { should include(url: project.url_to_repo) } - it { should include(description: project.description) } - it { should include(homepage: project.web_url) } + it { is_expected.to include(name: project.name) } + it { is_expected.to include(url: project.url_to_repo) } + it { is_expected.to include(description: project.description) } + it { is_expected.to include(homepage: project.web_url) } end end describe "Web Hooks" do context "execute web hooks" do it "when pushing tags" do - project.should_receive(:execute_hooks) + expect(project).to receive(:execute_hooks) service.execute(project, user, 'oldrev', 'newrev', 'refs/tags/v1.0.0') end end diff --git a/spec/services/issues/bulk_update_context_spec.rb b/spec/services/issues/bulk_update_context_spec.rb deleted file mode 100644 index f4c9148f1a3..00000000000 --- a/spec/services/issues/bulk_update_context_spec.rb +++ /dev/null @@ -1,110 +0,0 @@ -require 'spec_helper' - -describe Issues::BulkUpdateService do - let(:issue) { - create(:issue, project: @project) - } - - before do - @user = create :user - opts = { - name: "GitLab", - namespace: @user.namespace - } - @project = Projects::CreateService.new(@user, opts).execute - end - - describe :close_issue do - - before do - @issues = 5.times.collect do - create(:issue, project: @project) - end - @params = { - update: { - status: 'closed', - issues_ids: @issues.map(&:id) - } - } - end - - it { - result = Issues::BulkUpdateService.new(@project, @user, @params).execute - result[:success].should be_true - result[:count].should == @issues.count - - @project.issues.opened.should be_empty - @project.issues.closed.should_not be_empty - } - - end - - describe :reopen_issues do - - before do - @issues = 5.times.collect do - create(:closed_issue, project: @project) - end - @params = { - update: { - status: 'reopen', - issues_ids: @issues.map(&:id) - } - } - end - - it { - result = Issues::BulkUpdateService.new(@project, @user, @params).execute - result[:success].should be_true - result[:count].should == @issues.count - - @project.issues.closed.should be_empty - @project.issues.opened.should_not be_empty - } - - end - - describe :update_assignee do - - before do - @new_assignee = create :user - @params = { - update: { - issues_ids: [issue.id], - assignee_id: @new_assignee.id - } - } - end - - it { - result = Issues::BulkUpdateService.new(@project, @user, @params).execute - result[:success].should be_true - result[:count].should == 1 - - @project.issues.first.assignee.should == @new_assignee - } - - end - - describe :update_milestone do - - before do - @milestone = create :milestone - @params = { - update: { - issues_ids: [issue.id], - milestone_id: @milestone.id - } - } - end - - it { - result = Issues::BulkUpdateService.new(@project, @user, @params).execute - result[:success].should be_true - result[:count].should == 1 - - @project.issues.first.milestone.should == @milestone - } - end - -end diff --git a/spec/services/issues/bulk_update_service_spec.rb b/spec/services/issues/bulk_update_service_spec.rb new file mode 100644 index 00000000000..a97c55011c9 --- /dev/null +++ b/spec/services/issues/bulk_update_service_spec.rb @@ -0,0 +1,121 @@ +require 'spec_helper' + +describe Issues::BulkUpdateService do + let(:issue) { + create(:issue, project: @project) + } + + before do + @user = create :user + opts = { + name: "GitLab", + namespace: @user.namespace + } + @project = Projects::CreateService.new(@user, opts).execute + end + + describe :close_issue do + + before do + @issues = 5.times.collect do + create(:issue, project: @project) + end + @params = { + state_event: 'close', + issues_ids: @issues.map(&:id) + } + end + + it { + result = Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(result[:success]).to be_truthy + expect(result[:count]).to eq(@issues.count) + + expect(@project.issues.opened).to be_empty + expect(@project.issues.closed).not_to be_empty + } + + end + + describe :reopen_issues do + + before do + @issues = 5.times.collect do + create(:closed_issue, project: @project) + end + @params = { + state_event: 'reopen', + issues_ids: @issues.map(&:id) + } + end + + it { + result = Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(result[:success]).to be_truthy + expect(result[:count]).to eq(@issues.count) + + expect(@project.issues.closed).to be_empty + expect(@project.issues.opened).not_to be_empty + } + + end + + describe :update_assignee do + + before do + @new_assignee = create :user + @params = { + issues_ids: [issue.id], + assignee_id: @new_assignee.id + } + end + + it { + result = Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(result[:success]).to be_truthy + expect(result[:count]).to eq(1) + + expect(@project.issues.first.assignee).to eq(@new_assignee) + } + + it 'allows mass-unassigning' do + @project.issues.first.update_attribute(:assignee, @new_assignee) + expect(@project.issues.first.assignee).not_to be_nil + + @params[:assignee_id] = -1 + + Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(@project.issues.first.assignee).to be_nil + end + + it 'does not unassign when assignee_id is not present' do + @project.issues.first.update_attribute(:assignee, @new_assignee) + expect(@project.issues.first.assignee).not_to be_nil + + @params[:assignee_id] = '' + + Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(@project.issues.first.assignee).not_to be_nil + end + end + + describe :update_milestone do + + before do + @milestone = create :milestone + @params = { + issues_ids: [issue.id], + milestone_id: @milestone.id + } + end + + it { + result = Issues::BulkUpdateService.new(@project, @user, @params).execute + expect(result[:success]).to be_truthy + expect(result[:count]).to eq(1) + + expect(@project.issues.first.milestone).to eq(@milestone) + } + end + +end diff --git a/spec/services/issues/close_service_spec.rb b/spec/services/issues/close_service_spec.rb index d4f2cc1339b..d15dff1b52b 100644 --- a/spec/services/issues/close_service_spec.rb +++ b/spec/services/issues/close_service_spec.rb @@ -17,18 +17,18 @@ describe Issues::CloseService do @issue = Issues::CloseService.new(project, user, {}).execute(issue) end - it { @issue.should be_valid } - it { @issue.should be_closed } + it { expect(@issue).to be_valid } + it { expect(@issue).to be_closed } it 'should send email to user2 about assign of new issue' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email - email.subject.should include(issue.title) + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(issue.title) end it 'should create system note about issue reassign' do note = @issue.notes.last - note.note.should include "Status changed to closed" + expect(note.note).to include "Status changed to closed" end end end diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 90720be5ded..7f1ebcb3198 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -16,8 +16,8 @@ describe Issues::CreateService do @issue = Issues::CreateService.new(project, user, opts).execute end - it { @issue.should be_valid } - it { @issue.title.should == 'Awesome issue' } + it { expect(@issue).to be_valid } + it { expect(@issue.title).to eq('Awesome issue') } end end end diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index 347560414e7..22b89bec96d 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -5,6 +5,7 @@ describe Issues::UpdateService do let(:user) { create(:user) } let(:user2) { create(:user) } let(:issue) { create(:issue) } + let(:label) { create(:label) } before do project.team << [user, :master] @@ -18,26 +19,35 @@ describe Issues::UpdateService do title: 'New title', description: 'Also please fix', assignee_id: user2.id, - state_event: 'close' + state_event: 'close', + label_ids: [label.id] } @issue = Issues::UpdateService.new(project, user, opts).execute(issue) + @issue.reload end - it { @issue.should be_valid } - it { @issue.title.should == 'New title' } - it { @issue.assignee.should == user2 } - it { @issue.should be_closed } + it { expect(@issue).to be_valid } + it { expect(@issue.title).to eq('New title') } + it { expect(@issue.assignee).to eq(user2) } + it { expect(@issue).to be_closed } + it { expect(@issue.labels.count).to eq(1) } + it { expect(@issue.labels.first.title).to eq('Bug') } it 'should send email to user2 about assign of new issue' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email - email.subject.should include(issue.title) + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(issue.title) end it 'should create system note about issue reassign' do note = @issue.notes.last - note.note.should include "Reassigned to \@#{user2.username}" + expect(note.note).to include "Reassigned to \@#{user2.username}" + end + + it 'should create system note about issue label edit' do + note = @issue.notes[1] + expect(note.note).to include "Added ~#{label.id} label" end end end diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb index a504f916b08..b3cbfd4b5b8 100644 --- a/spec/services/merge_requests/close_service_spec.rb +++ b/spec/services/merge_requests/close_service_spec.rb @@ -12,23 +12,32 @@ describe MergeRequests::CloseService do end describe :execute do - context "valid params" do + context 'valid params' do + let(:service) { MergeRequests::CloseService.new(project, user, {}) } + before do - @merge_request = MergeRequests::CloseService.new(project, user, {}).execute(merge_request) + allow(service).to receive(:execute_hooks) + + @merge_request = service.execute(merge_request) end - it { @merge_request.should be_valid } - it { @merge_request.should be_closed } + it { expect(@merge_request).to be_valid } + it { expect(@merge_request).to be_closed } + + it 'should execute hooks with close action' do + expect(service).to have_received(:execute_hooks). + with(@merge_request, 'close') + end it 'should send email to user2 about assign of new merge_request' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email - email.subject.should include(merge_request.title) + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(merge_request.title) end it 'should create system note about merge_request reassign' do note = @merge_request.notes.last - note.note.should include "Status changed to closed" + expect(note.note).to include 'Status changed to closed' end end end diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index cebeb0644d0..d9bfdf64308 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -5,21 +5,30 @@ describe MergeRequests::CreateService do let(:user) { create(:user) } describe :execute do - context "valid params" do - before do - project.team << [user, :master] - opts = { + context 'valid params' do + let(:opts) do + { title: 'Awesome merge_request', description: 'please fix', source_branch: 'stable', target_branch: 'master' } + end + let(:service) { MergeRequests::CreateService.new(project, user, opts) } + + before do + project.team << [user, :master] + allow(service).to receive(:execute_hooks) - @merge_request = MergeRequests::CreateService.new(project, user, opts).execute + @merge_request = service.execute end - it { @merge_request.should be_valid } - it { @merge_request.title.should == 'Awesome merge_request' } + it { expect(@merge_request).to be_valid } + it { expect(@merge_request.title).to eq('Awesome merge_request') } + + it 'should execute hooks with default action' do + expect(service).to have_received(:execute_hooks).with(@merge_request) + end end end end diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb new file mode 100644 index 00000000000..0a25fb12f4e --- /dev/null +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe MergeRequests::MergeService do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:merge_request) { create(:merge_request, assignee: user2) } + let(:project) { merge_request.project } + + before do + project.team << [user, :master] + project.team << [user2, :developer] + end + + describe :execute do + context 'valid params' do + let(:service) { MergeRequests::MergeService.new(project, user, {}) } + + before do + allow(service).to receive(:execute_hooks) + + service.execute(merge_request, 'Awesome message') + end + + it { expect(merge_request).to be_valid } + it { expect(merge_request).to be_merged } + + it 'should execute hooks with merge action' do + expect(service).to have_received(:execute_hooks). + with(merge_request, 'merge') + end + + it 'should send email to user2 about merge of new merge_request' do + email = ActionMailer::Base.deliveries.last + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(merge_request.title) + end + + it 'should create system note about merge_request merge' do + note = merge_request.notes.last + expect(note.note).to include 'Status changed to merged' + end + end + end +end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb new file mode 100644 index 00000000000..879df0c9c67 --- /dev/null +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' + +describe MergeRequests::RefreshService do + let(:project) { create(:project) } + let(:user) { create(:user) } + let(:service) { MergeRequests::RefreshService } + + describe :execute do + before do + @user = create(:user) + group = create(:group) + group.add_owner(@user) + + @project = create(:project, namespace: group) + @fork_project = Projects::ForkService.new(@project, @user).execute + @merge_request = create(:merge_request, source_project: @project, + source_branch: 'master', + target_branch: 'feature', + target_project: @project) + + @fork_merge_request = create(:merge_request, source_project: @fork_project, + source_branch: 'master', + target_branch: 'feature', + target_project: @project) + + @commits = @merge_request.commits + + @oldrev = @commits.last.id + @newrev = @commits.first.id + end + + context 'push to origin repo source branch' do + before do + service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/master') + reload_mrs + end + + it { expect(@merge_request.notes).not_to be_empty } + it { expect(@merge_request).to be_open } + it { expect(@fork_merge_request).to be_open } + it { expect(@fork_merge_request.notes).to be_empty } + end + + context 'push to origin repo target branch' do + before do + service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature') + reload_mrs + end + + it { expect(@merge_request.notes.last.note).to include('changed to merged') } + it { expect(@merge_request).to be_merged } + it { expect(@fork_merge_request).to be_merged } + it { expect(@fork_merge_request.notes.last.note).to include('changed to merged') } + end + + context 'push to fork repo source branch' do + before do + service.new(@fork_project, @user).execute(@oldrev, @newrev, 'refs/heads/master') + reload_mrs + end + + it { expect(@merge_request.notes).to be_empty } + it { expect(@merge_request).to be_open } + it { expect(@fork_merge_request.notes.last.note).to include('Added 4 commits') } + it { expect(@fork_merge_request).to be_open } + end + + context 'push to fork repo target branch' do + before do + service.new(@fork_project, @user).execute(@oldrev, @newrev, 'refs/heads/feature') + reload_mrs + end + + it { expect(@merge_request.notes).to be_empty } + it { expect(@merge_request).to be_open } + it { expect(@fork_merge_request.notes).to be_empty } + it { expect(@fork_merge_request).to be_open } + end + + context 'push to origin repo target branch after fork project was removed' do + before do + @fork_project.destroy + service.new(@project, @user).execute(@oldrev, @newrev, 'refs/heads/feature') + reload_mrs + end + + it { expect(@merge_request.notes.last.note).to include('changed to merged') } + it { expect(@merge_request).to be_merged } + it { expect(@fork_merge_request).to be_open } + it { expect(@fork_merge_request.notes).to be_empty } + end + + def reload_mrs + @merge_request.reload + @fork_merge_request.reload + end + end +end diff --git a/spec/services/merge_requests/reopen_service_spec.rb b/spec/services/merge_requests/reopen_service_spec.rb new file mode 100644 index 00000000000..9401bc3b558 --- /dev/null +++ b/spec/services/merge_requests/reopen_service_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe MergeRequests::ReopenService do + let(:user) { create(:user) } + let(:user2) { create(:user) } + let(:merge_request) { create(:merge_request, assignee: user2) } + let(:project) { merge_request.project } + + before do + project.team << [user, :master] + project.team << [user2, :developer] + end + + describe :execute do + context 'valid params' do + let(:service) { MergeRequests::ReopenService.new(project, user, {}) } + + before do + allow(service).to receive(:execute_hooks) + + merge_request.state = :closed + service.execute(merge_request) + end + + it { expect(merge_request).to be_valid } + it { expect(merge_request).to be_reopened } + + it 'should execute hooks with reopen action' do + expect(service).to have_received(:execute_hooks). + with(merge_request, 'reopen') + end + + it 'should send email to user2 about reopen of merge_request' do + email = ActionMailer::Base.deliveries.last + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(merge_request.title) + end + + it 'should create system note about merge_request reopen' do + note = merge_request.notes.last + expect(note.note).to include 'Status changed to reopened' + end + end + end +end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index af5d3a3dc81..916b01e1c45 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -5,6 +5,7 @@ describe MergeRequests::UpdateService do let(:user2) { create(:user) } let(:merge_request) { create(:merge_request, :simple) } let(:project) { merge_request.project } + let(:label) { create(:label) } before do project.team << [user, :master] @@ -12,32 +13,52 @@ describe MergeRequests::UpdateService do end describe :execute do - context "valid params" do - before do - opts = { + context 'valid params' do + let(:opts) do + { title: 'New title', description: 'Also please fix', assignee_id: user2.id, - state_event: 'close' + state_event: 'close', + label_ids: [label.id] } + end + + let(:service) { MergeRequests::UpdateService.new(project, user, opts) } + + before do + allow(service).to receive(:execute_hooks) - @merge_request = MergeRequests::UpdateService.new(project, user, opts).execute(merge_request) + @merge_request = service.execute(merge_request) + @merge_request.reload end - it { @merge_request.should be_valid } - it { @merge_request.title.should == 'New title' } - it { @merge_request.assignee.should == user2 } - it { @merge_request.should be_closed } + it { expect(@merge_request).to be_valid } + it { expect(@merge_request.title).to eq('New title') } + it { expect(@merge_request.assignee).to eq(user2) } + it { expect(@merge_request).to be_closed } + it { expect(@merge_request.labels.count).to eq(1) } + it { expect(@merge_request.labels.first.title).to eq('Bug') } + + it 'should execute hooks with update action' do + expect(service).to have_received(:execute_hooks). + with(@merge_request, 'update') + end it 'should send email to user2 about assign of new merge_request' do email = ActionMailer::Base.deliveries.last - email.to.first.should == user2.email - email.subject.should include(merge_request.title) + expect(email.to.first).to eq(user2.email) + expect(email.subject).to include(merge_request.title) end it 'should create system note about merge_request reassign' do note = @merge_request.notes.last - note.note.should include "Reassigned to \@#{user2.username}" + expect(note.note).to include "Reassigned to \@#{user2.username}" + end + + it 'should create system note about merge_request label edit' do + note = @merge_request.notes[1] + expect(note.note).to include "Added ~#{label.id} label" end end end diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index f59786efcf9..1a02299bf19 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -18,8 +18,8 @@ describe Notes::CreateService do @note = Notes::CreateService.new(project, user, opts).execute end - it { @note.should be_valid } - it { @note.note.should == 'Awesome comment' } + it { expect(@note).to be_valid } + it { expect(@note.note).to eq('Awesome comment') } end end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index f8377650e0a..bfca2c88264 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -7,10 +7,10 @@ describe NotificationService do describe :new_key do let!(:key) { create(:personal_key) } - it { notification.new_key(key).should be_true } + it { expect(notification.new_key(key)).to be_truthy } it 'should sent email to key owner' do - Notify.should_receive(:new_ssh_key_email).with(key.id) + expect(Notify).to receive(:new_ssh_key_email).with(key.id) notification.new_key(key) end end @@ -20,10 +20,10 @@ describe NotificationService do describe :new_email do let!(:email) { create(:email) } - it { notification.new_email(email).should be_true } + it { expect(notification.new_email(email)).to be_truthy } it 'should send email to email owner' do - Notify.should_receive(:new_email_email).with(email.id) + expect(Notify).to receive(:new_email_email).with(email.id) notification.new_email(email) end end @@ -41,20 +41,25 @@ describe NotificationService do describe :new_note do it do + add_users_with_subscription(note.project, issue) + should_email(@u_watcher.id) should_email(note.noteable.author_id) should_email(note.noteable.assignee_id) should_email(@u_mentioned.id) + should_email(@subscriber.id) should_not_email(note.author_id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) + should_not_email(@unsubscriber.id) + notification.new_note(note) end it 'filters out "mentioned in" notes' do mentioned_note = Note.create_cross_reference_note(mentioned_issue, issue, issue.author, issue.project) - Notify.should_not_receive(:note_issue_email) + expect(Notify).not_to receive(:note_issue_email) notification.new_note(mentioned_note) end end @@ -69,9 +74,9 @@ describe NotificationService do user_project = note.project.project_members.find_by_user_id(@u_watcher.id) user_project.notification_level = Notification::N_PARTICIPATING user_project.save - user_group = note.project.group.group_members.find_by_user_id(@u_watcher.id) - user_group.notification_level = Notification::N_GLOBAL - user_group.save + group_member = note.project.group.group_members.find_by_user_id(@u_watcher.id) + group_member.notification_level = Notification::N_GLOBAL + group_member.save end it do @@ -87,11 +92,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:note_issue_email).with(user_id, note.id) + expect(Notify).to receive(:note_issue_email).with(user_id, note.id) end def should_not_email(user_id) - Notify.should_not_receive(:note_issue_email).with(user_id, note.id) + expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id) end end @@ -116,6 +121,7 @@ describe NotificationService do should_email(note.noteable.assignee_id) should_not_email(note.author_id) + should_not_email(@u_mentioned.id) should_not_email(@u_disabled.id) should_not_email(@u_not_mentioned.id) notification.new_note(note) @@ -124,17 +130,17 @@ describe NotificationService do it 'filters out "mentioned in" notes' do mentioned_note = Note.create_cross_reference_note(mentioned_issue, issue, issue.author, issue.project) - Notify.should_not_receive(:note_issue_email) + expect(Notify).not_to receive(:note_issue_email) notification.new_note(mentioned_note) end end def should_email(user_id) - Notify.should_receive(:note_issue_email).with(user_id, note.id) + expect(Notify).to receive(:note_issue_email).with(user_id, note.id) end def should_not_email(user_id) - Notify.should_not_receive(:note_issue_email).with(user_id, note.id) + expect(Notify).not_to receive(:note_issue_email).with(user_id, note.id) end end @@ -168,39 +174,54 @@ describe NotificationService do notification.new_note(note) end + it do + @u_committer.update_attributes(notification_level: Notification::N_MENTION) + should_not_email(@u_committer.id, note) + notification.new_note(note) + end + def should_email(user_id, n) - Notify.should_receive(:note_commit_email).with(user_id, n.id) + expect(Notify).to receive(:note_commit_email).with(user_id, n.id) end def should_not_email(user_id, n) - Notify.should_not_receive(:note_commit_email).with(user_id, n.id) + expect(Notify).not_to receive(:note_commit_email).with(user_id, n.id) end end end end describe 'Issues' do - let(:issue) { create :issue, assignee: create(:user) } + let(:issue) { create :issue, assignee: create(:user), description: 'cc @participant' } before do build_team(issue.project) + add_users_with_subscription(issue.project, issue) end describe :new_issue do it do should_email(issue.assignee_id) should_email(@u_watcher.id) + should_email(@u_participant_mentioned.id) + should_not_email(@u_mentioned.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.new_issue(issue, @u_disabled) end + it do + issue.assignee.update_attributes(notification_level: Notification::N_MENTION) + should_not_email(issue.assignee_id) + notification.new_issue(issue, @u_disabled) + end + def should_email(user_id) - Notify.should_receive(:new_issue_email).with(user_id, issue.id) + expect(Notify).to receive(:new_issue_email).with(user_id, issue.id) end def should_not_email(user_id) - Notify.should_not_receive(:new_issue_email).with(user_id, issue.id) + expect(Notify).not_to receive(:new_issue_email).with(user_id, issue.id) end end @@ -208,6 +229,9 @@ describe NotificationService do it 'should email new assignee' do should_email(issue.assignee_id) should_email(@u_watcher.id) + should_email(@u_participant_mentioned.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) @@ -215,11 +239,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id) + expect(Notify).to receive(:reassigned_issue_email).with(user_id, issue.id, nil, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id) + expect(Notify).not_to receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id) end end @@ -228,6 +252,9 @@ describe NotificationService do should_email(issue.assignee_id) should_email(issue.author_id) should_email(@u_watcher.id) + should_email(@u_participant_mentioned.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) @@ -235,11 +262,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) + expect(Notify).to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) + expect(Notify).not_to receive(:closed_issue_email).with(user_id, issue.id, @u_disabled.id) end end @@ -248,6 +275,9 @@ describe NotificationService do should_email(issue.assignee_id) should_email(issue.author_id) should_email(@u_watcher.id) + should_email(@u_participant_mentioned.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) @@ -255,11 +285,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id) + expect(Notify).to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id) + expect(Notify).not_to receive(:issue_status_changed_email).with(user_id, issue.id, 'reopened', @u_disabled.id) end end end @@ -269,6 +299,7 @@ describe NotificationService do before do build_team(merge_request.target_project) + add_users_with_subscription(merge_request.target_project, merge_request) end describe :new_merge_request do @@ -281,11 +312,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:new_merge_request_email).with(user_id, merge_request.id) + expect(Notify).to receive(:new_merge_request_email).with(user_id, merge_request.id) end def should_not_email(user_id) - Notify.should_not_receive(:new_merge_request_email).with(user_id, merge_request.id) + expect(Notify).not_to receive(:new_merge_request_email).with(user_id, merge_request.id) end end @@ -293,17 +324,19 @@ describe NotificationService do it do should_email(merge_request.assignee_id) should_email(@u_watcher.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.reassigned_merge_request(merge_request, merge_request.author) end def should_email(user_id) - Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id) + expect(Notify).to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, nil, merge_request.author_id) end def should_not_email(user_id) - Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id) + expect(Notify).not_to receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id) end end @@ -311,17 +344,19 @@ describe NotificationService do it do should_email(merge_request.assignee_id) should_email(@u_watcher.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.close_mr(merge_request, @u_disabled) end def should_email(user_id) - Notify.should_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + expect(Notify).to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + expect(Notify).not_to receive(:closed_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end end @@ -329,17 +364,19 @@ describe NotificationService do it do should_email(merge_request.assignee_id) should_email(@u_watcher.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.merge_mr(merge_request, @u_disabled) end def should_email(user_id) - Notify.should_receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + expect(Notify).to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) + expect(Notify).not_to receive(:merged_merge_request_email).with(user_id, merge_request.id, @u_disabled.id) end end @@ -347,17 +384,19 @@ describe NotificationService do it do should_email(merge_request.assignee_id) should_email(@u_watcher.id) + should_email(@subscriber.id) + should_not_email(@unsubscriber.id) should_not_email(@u_participating.id) should_not_email(@u_disabled.id) notification.reopen_mr(merge_request, @u_disabled) end def should_email(user_id) - Notify.should_receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) + expect(Notify).to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) end def should_not_email(user_id) - Notify.should_not_receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) + expect(Notify).not_to receive(:merge_request_status_email).with(user_id, merge_request.id, 'reopened', @u_disabled.id) end end end @@ -378,11 +417,11 @@ describe NotificationService do end def should_email(user_id) - Notify.should_receive(:project_was_moved_email).with(project.id, user_id) + expect(Notify).to receive(:project_was_moved_email).with(project.id, user_id) end def should_not_email(user_id) - Notify.should_not_receive(:project_was_moved_email).with(project.id, user_id) + expect(Notify).not_to receive(:project_was_moved_email).with(project.id, user_id) end end end @@ -390,8 +429,9 @@ describe NotificationService do def build_team(project) @u_watcher = create(:user, notification_level: Notification::N_WATCH) @u_participating = create(:user, notification_level: Notification::N_PARTICIPATING) + @u_participant_mentioned = create(:user, username: 'participant', notification_level: Notification::N_PARTICIPATING) @u_disabled = create(:user, notification_level: Notification::N_DISABLED) - @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_PARTICIPATING) + @u_mentioned = create(:user, username: 'mention', notification_level: Notification::N_MENTION) @u_committer = create(:user, username: 'committer') @u_not_mentioned = create(:user, username: 'regular', notification_level: Notification::N_PARTICIPATING) @@ -401,4 +441,15 @@ describe NotificationService do project.team << [@u_mentioned, :master] project.team << [@u_committer, :master] end + + def add_users_with_subscription(project, issuable) + @subscriber = create :user + @unsubscriber = create :user + + project.team << [@subscriber, :master] + project.team << [@unsubscriber, :master] + + issuable.subscriptions.create(user: @subscriber, subscribed: true) + issuable.subscriptions.create(user: @unsubscriber, subscribed: false) + end end diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 9c97dad2ff0..337dae592dd 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -16,9 +16,9 @@ describe Projects::CreateService do @project = create_project(@user, @opts) end - it { @project.should be_valid } - it { @project.owner.should == @user } - it { @project.namespace.should == @user.namespace } + it { expect(@project).to be_valid } + it { expect(@project.owner).to eq(@user) } + it { expect(@project.namespace).to eq(@user.namespace) } end context 'group namespace' do @@ -30,9 +30,9 @@ describe Projects::CreateService do @project = create_project(@user, @opts) end - it { @project.should be_valid } - it { @project.owner.should == @group } - it { @project.namespace.should == @group } + it { expect(@project).to be_valid } + it { expect(@project.owner).to eq(@group) } + it { expect(@project.namespace).to eq(@group) } end context 'wiki_enabled creates repository directory' do @@ -42,7 +42,7 @@ describe Projects::CreateService do @path = ProjectWiki.new(@project, @user).send(:path_to_repo) end - it { File.exists?(@path).should be_true } + it { expect(File.exists?(@path)).to be_truthy } end context 'wiki_enabled false does not create wiki repository directory' do @@ -52,7 +52,34 @@ describe Projects::CreateService do @path = ProjectWiki.new(@project, @user).send(:path_to_repo) end - it { File.exists?(@path).should be_false } + it { expect(File.exists?(@path)).to be_falsey } + end + end + + context 'restricted visibility level' do + before do + allow_any_instance_of(ApplicationSetting).to( + receive(:restricted_visibility_levels).and_return([20]) + ) + + @opts.merge!( + visibility_level: Gitlab::VisibilityLevel.options['Public'] + ) + end + + it 'should not allow a restricted visibility level for non-admins' do + project = create_project(@user, @opts) + expect(project).to respond_to(:errors) + expect(project.errors.messages).to have_key(:visibility_level) + expect(project.errors.messages[:visibility_level].first).to( + match('restricted by your GitLab administrator') + ) + end + + it 'should allow a restricted visibility level for admins' do + project = create_project(@admin, @opts) + expect(project.errors.any?).to be(false) + expect(project.saved?).to be(true) end end end diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index 0edc3a8e807..e55a2e3f8a0 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -16,18 +16,18 @@ describe Projects::ForkService do describe "successfully creates project in the user namespace" do let(:to_project) { fork_project(@from_project, @to_user) } - it { to_project.owner.should == @to_user } - it { to_project.namespace.should == @to_user.namespace } - it { to_project.star_count.should be_zero } - it { to_project.description.should == @from_project.description } + it { expect(to_project.owner).to eq(@to_user) } + it { expect(to_project.namespace).to eq(@to_user.namespace) } + it { expect(to_project.star_count).to be_zero } + it { expect(to_project.description).to eq(@from_project.description) } end end context 'fork project failure' do it "fails due to transaction failure" do @to_project = fork_project(@from_project, @to_user, false) - @to_project.errors.should_not be_empty - @to_project.errors[:base].should include("Fork transaction failed.") + expect(@to_project.errors).not_to be_empty + expect(@to_project.errors[:base]).to include("Fork transaction failed.") end end @@ -35,17 +35,61 @@ describe Projects::ForkService do it "should fail due to validation, not transaction failure" do @existing_project = create(:project, creator_id: @to_user.id, name: @from_project.name, namespace: @to_namespace) @to_project = fork_project(@from_project, @to_user) - @existing_project.persisted?.should be_true - @to_project.errors[:base].should include("Invalid fork destination") - @to_project.errors[:base].should_not include("Fork transaction failed.") + expect(@existing_project.persisted?).to be_truthy + expect(@to_project.errors[:base]).to include("Invalid fork destination") + expect(@to_project.errors[:base]).not_to include("Fork transaction failed.") end end end - def fork_project(from_project, user, fork_success = true) - context = Projects::ForkService.new(from_project, user) - shell = double("gitlab_shell") - shell.stub(fork_repository: fork_success) + describe :fork_to_namespace do + before do + @group_owner = create(:user) + @developer = create(:user) + @project = create(:project, creator_id: @group_owner.id, + star_count: 777, + description: 'Wow, such a cool project!') + @group = create(:group) + @group.add_user(@group_owner, GroupMember::OWNER) + @group.add_user(@developer, GroupMember::DEVELOPER) + @opts = { namespace: @group } + end + + context 'fork project for group' do + it 'group owner successfully forks project into the group' do + to_project = fork_project(@project, @group_owner, true, @opts) + expect(to_project.owner).to eq(@group) + expect(to_project.namespace).to eq(@group) + expect(to_project.name).to eq(@project.name) + expect(to_project.path).to eq(@project.path) + expect(to_project.description).to eq(@project.description) + expect(to_project.star_count).to be_zero + end + end + + context 'fork project for group when user not owner' do + it 'group developer should fail to fork project into the group' do + to_project = fork_project(@project, @developer, true, @opts) + expect(to_project.errors[:namespace]).to eq(['insufficient access rights']) + end + end + + context 'project already exists in group' do + it 'should fail due to validation, not transaction failure' do + existing_project = create(:project, name: @project.name, + namespace: @group) + to_project = fork_project(@project, @group_owner, true, @opts) + expect(existing_project.persisted?).to be_truthy + expect(to_project.errors[:base]).to eq(['Invalid fork destination']) + expect(to_project.errors[:name]).to eq(['has already been taken']) + expect(to_project.errors[:path]).to eq(['has already been taken']) + end + end + end + + def fork_project(from_project, user, fork_success = true, params = {}) + context = Projects::ForkService.new(from_project, user, params) + shell = double('gitlab_shell').stub(fork_repository: fork_success) context.stub(gitlab_shell: shell) context.execute end diff --git a/spec/services/projects/image_service_spec.rb b/spec/services/projects/image_service_spec.rb deleted file mode 100644 index 23c4e227ae3..00000000000 --- a/spec/services/projects/image_service_spec.rb +++ /dev/null @@ -1,62 +0,0 @@ -require 'spec_helper' - -describe Projects::ImageService do - describe 'Image service' do - before do - @user = create :user - @project = create :project, creator_id: @user.id, namespace: @user.namespace - end - - context 'for valid gif file' do - before do - gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') - @link_to_image = upload_image(@project.repository, { 'markdown_img' => gif }, "http://test.example/") - end - - it { expect(@link_to_image).to have_key("alt") } - it { expect(@link_to_image).to have_key("url") } - it { expect(@link_to_image).to have_value("banana_sample") } - it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } - it { expect(@link_to_image["url"]).to match("banana_sample.gif") } - end - - context 'for valid png file' do - before do - png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/png') - @link_to_image = upload_image(@project.repository, { 'markdown_img' => png }, "http://test.example/") - end - - it { expect(@link_to_image).to have_key("alt") } - it { expect(@link_to_image).to have_key("url") } - it { expect(@link_to_image).to have_value("dk") } - it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } - it { expect(@link_to_image["url"]).to match("dk.png") } - end - - context 'for valid jpg file' do - before do - jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') - @link_to_image = upload_image(@project.repository, { 'markdown_img' => jpg }, "http://test.example/") - end - - it { expect(@link_to_image).to have_key("alt") } - it { expect(@link_to_image).to have_key("url") } - it { expect(@link_to_image).to have_value("rails_sample") } - it { expect(@link_to_image["url"]).to match("http://test.example/uploads/#{@project.path_with_namespace}") } - it { expect(@link_to_image["url"]).to match("rails_sample.jpg") } - end - - context 'for txt file' do - before do - txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') - @link_to_image = upload_image(@project.repository, { 'markdown_img' => txt }, "http://test.example/") - end - - it { expect(@link_to_image).to be_nil } - end - end - - def upload_image(repository, params, root_url) - Projects::ImageService.new(repository, params, root_url).execute - end -end diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb index 2508dfc4565..5650626fb18 100644 --- a/spec/services/projects/transfer_service_spec.rb +++ b/spec/services/projects/transfer_service_spec.rb @@ -3,41 +3,39 @@ require 'spec_helper' describe Projects::TransferService do let(:user) { create(:user) } let(:group) { create(:group) } - let(:group2) { create(:group) } let(:project) { create(:project, namespace: user.namespace) } context 'namespace -> namespace' do before do group.add_owner(user) - @service = Projects::TransferService.new(project, user, namespace_id: group.id) - @service.gitlab_shell.stub(mv_repository: true) - @result = @service.execute + @result = transfer_project(project, user, new_namespace_id: group.id) end - it { @result.should be_true } - it { project.namespace.should == group } + it { expect(@result).to be_truthy } + it { expect(project.namespace).to eq(group) } end context 'namespace -> no namespace' do before do - group.add_owner(user) - @service = Projects::TransferService.new(project, user, namespace_id: nil) - @service.gitlab_shell.stub(mv_repository: true) - @result = @service.execute + @result = transfer_project(project, user, new_namespace_id: nil) end - it { @result.should be_false } - it { project.namespace.should == user.namespace } + it { expect(@result).not_to be_nil } # { result.should be_false } passes on nil + it { expect(@result).to be_falsey } + it { expect(project.namespace).to eq(user.namespace) } end context 'namespace -> not allowed namespace' do before do - @service = Projects::TransferService.new(project, user, namespace_id: group2.id) - @service.gitlab_shell.stub(mv_repository: true) - @result = @service.execute + @result = transfer_project(project, user, new_namespace_id: group.id) end - it { @result.should be_false } - it { project.namespace.should == user.namespace } + it { expect(@result).not_to be_nil } # { result.should be_false } passes on nil + it { expect(@result).to be_falsey } + it { expect(project.namespace).to eq(user.namespace) } + end + + def transfer_project(project, user, params) + Projects::TransferService.new(project, user, params).execute end end diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb index 5a10174eb36..ea5b8813105 100644 --- a/spec/services/projects/update_service_spec.rb +++ b/spec/services/projects/update_service_spec.rb @@ -17,8 +17,8 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.private?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.private?).to be_truthy } end context 'should be internal when updated to internal' do @@ -29,8 +29,8 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.internal?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.internal?).to be_truthy } end context 'should be public when updated to public' do @@ -41,15 +41,15 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.public?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.public?).to be_truthy } end context 'respect configured visibility restrictions setting' do before(:each) do - @restrictions = double("restrictions") - @restrictions.stub(:restricted_visibility_levels) { [ "public" ] } - Settings.stub_chain(:gitlab).and_return(@restrictions) + allow_any_instance_of(ApplicationSetting).to( + receive(:restricted_visibility_levels).and_return([20]) + ) end context 'should be private when updated to private' do @@ -60,8 +60,8 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.private?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.private?).to be_truthy } end context 'should be internal when updated to internal' do @@ -72,8 +72,8 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.internal?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.internal?).to be_truthy } end context 'should be private when updated to public' do @@ -84,8 +84,8 @@ describe Projects::UpdateService do update_project(@project, @user, @opts) end - it { @created_private.should be_true } - it { @project.private?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.private?).to be_truthy } end context 'should be public when updated to public by admin' do @@ -96,8 +96,8 @@ describe Projects::UpdateService do update_project(@project, @admin, @opts) end - it { @created_private.should be_true } - it { @project.public?.should be_true } + it { expect(@created_private).to be_truthy } + it { expect(@project.public?).to be_truthy } end end end diff --git a/spec/services/projects/upload_service_spec.rb b/spec/services/projects/upload_service_spec.rb new file mode 100644 index 00000000000..fc34b456482 --- /dev/null +++ b/spec/services/projects/upload_service_spec.rb @@ -0,0 +1,75 @@ +require 'spec_helper' + +describe Projects::UploadService do + describe 'File service' do + before do + @user = create :user + @project = create :project, creator_id: @user.id, namespace: @user.namespace + end + + context 'for valid gif file' do + before do + gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + @link_to_file = upload_file(@project.repository, gif) + end + + it { expect(@link_to_file).to have_key('alt') } + it { expect(@link_to_file).to have_key('url') } + it { expect(@link_to_file).to have_key('is_image') } + it { expect(@link_to_file).to have_value('banana_sample') } + it { expect(@link_to_file['is_image']).to equal(true) } + it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") } + it { expect(@link_to_file['url']).to match('banana_sample.gif') } + end + + context 'for valid png file' do + before do + png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', + 'image/png') + @link_to_file = upload_file(@project.repository, png) + end + + it { expect(@link_to_file).to have_key('alt') } + it { expect(@link_to_file).to have_key('url') } + it { expect(@link_to_file).to have_value('dk') } + it { expect(@link_to_file).to have_key('is_image') } + it { expect(@link_to_file['is_image']).to equal(true) } + it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") } + it { expect(@link_to_file['url']).to match('dk.png') } + end + + context 'for valid jpg file' do + before do + jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') + @link_to_file = upload_file(@project.repository, jpg) + end + + it { expect(@link_to_file).to have_key('alt') } + it { expect(@link_to_file).to have_key('url') } + it { expect(@link_to_file).to have_key('is_image') } + it { expect(@link_to_file).to have_value('rails_sample') } + it { expect(@link_to_file['is_image']).to equal(true) } + it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") } + it { expect(@link_to_file['url']).to match('rails_sample.jpg') } + end + + context 'for txt file' do + before do + txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') + @link_to_file = upload_file(@project.repository, txt) + end + + it { expect(@link_to_file).to have_key('alt') } + it { expect(@link_to_file).to have_key('url') } + it { expect(@link_to_file).to have_key('is_image') } + it { expect(@link_to_file).to have_value('doc_sample.txt') } + it { expect(@link_to_file['is_image']).to equal(false) } + it { expect(@link_to_file['url']).to match("/#{@project.path_with_namespace}") } + it { expect(@link_to_file['url']).to match('doc_sample.txt') } + end + end + + def upload_file(repository, file) + Projects::UploadService.new(repository, file).execute + end +end diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb index 3217c571e67..f57bfaea879 100644 --- a/spec/services/search_service_spec.rb +++ b/spec/services/search_service_spec.rb @@ -19,7 +19,7 @@ describe 'Search::GlobalService' do it 'should return public projects only' do context = Search::GlobalService.new(nil, search: "searchable") results = context.execute - results.objects('projects').should match_array [public_project] + expect(results.objects('projects')).to match_array [public_project] end end @@ -27,19 +27,19 @@ describe 'Search::GlobalService' do it 'should return public, internal and private projects' do context = Search::GlobalService.new(user, search: "searchable") results = context.execute - results.objects('projects').should match_array [public_project, found_project, internal_project] + expect(results.objects('projects')).to match_array [public_project, found_project, internal_project] end it 'should return only public & internal projects' do context = Search::GlobalService.new(internal_user, search: "searchable") results = context.execute - results.objects('projects').should match_array [internal_project, public_project] + expect(results.objects('projects')).to match_array [internal_project, public_project] end it 'namespace name should be searchable' do context = Search::GlobalService.new(user, search: found_project.namespace.path) results = context.execute - results.objects('projects').should match_array [found_project] + expect(results.objects('projects')).to match_array [found_project] end end end diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb index 573446d3a19..199ac996608 100644 --- a/spec/services/system_hooks_service_spec.rb +++ b/spec/services/system_hooks_service_spec.rb @@ -5,27 +5,58 @@ describe SystemHooksService do let (:project) { create :project } let (:project_member) { create :project_member } let (:key) { create(:key, user: user) } + let (:group) { create(:group) } + let (:group_member) { create(:group_member) } context 'event data' do - it { event_data(user, :create).should include(:event_name, :name, :created_at, :email, :user_id) } - it { event_data(user, :destroy).should include(:event_name, :name, :created_at, :email, :user_id) } - it { event_data(project, :create).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) } - it { event_data(project, :destroy).should include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) } - it { event_data(project_member, :create).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } - it { event_data(project_member, :destroy).should include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } - it { event_data(key, :create).should include(:username, :key, :id) } - it { event_data(key, :destroy).should include(:username, :key, :id) } + it { expect(event_data(user, :create)).to include(:event_name, :name, :created_at, :email, :user_id) } + it { expect(event_data(user, :destroy)).to include(:event_name, :name, :created_at, :email, :user_id) } + it { expect(event_data(project, :create)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) } + it { expect(event_data(project, :destroy)).to include(:event_name, :name, :created_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) } + it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } + it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :project_name, :project_path, :project_id, :user_name, :user_email, :access_level, :project_visibility) } + it { expect(event_data(key, :create)).to include(:username, :key, :id) } + it { expect(event_data(key, :destroy)).to include(:username, :key, :id) } + + it do + expect(event_data(group, :create)).to include( + :event_name, :name, :created_at, :path, :group_id, :owner_name, + :owner_email + ) + end + it do + expect(event_data(group, :destroy)).to include( + :event_name, :name, :created_at, :path, :group_id, :owner_name, + :owner_email + ) + end + it do + expect(event_data(group_member, :create)).to include( + :event_name, :created_at, :group_name, :group_path, :group_id, :user_id, + :user_name, :user_email, :group_access + ) + end + it do + expect(event_data(group_member, :destroy)).to include( + :event_name, :created_at, :group_name, :group_path, :group_id, :user_id, + :user_name, :user_email, :group_access + ) + end end context 'event names' do - it { event_name(user, :create).should eq "user_create" } - it { event_name(user, :destroy).should eq "user_destroy" } - it { event_name(project, :create).should eq "project_create" } - it { event_name(project, :destroy).should eq "project_destroy" } - it { event_name(project_member, :create).should eq "user_add_to_team" } - it { event_name(project_member, :destroy).should eq "user_remove_from_team" } - it { event_name(key, :create).should eq 'key_create' } - it { event_name(key, :destroy).should eq 'key_destroy' } + it { expect(event_name(user, :create)).to eq "user_create" } + it { expect(event_name(user, :destroy)).to eq "user_destroy" } + it { expect(event_name(project, :create)).to eq "project_create" } + it { expect(event_name(project, :destroy)).to eq "project_destroy" } + it { expect(event_name(project_member, :create)).to eq "user_add_to_team" } + it { expect(event_name(project_member, :destroy)).to eq "user_remove_from_team" } + it { expect(event_name(key, :create)).to eq 'key_create' } + it { expect(event_name(key, :destroy)).to eq 'key_destroy' } + it { expect(event_name(group, :create)).to eq 'group_create' } + it { expect(event_name(group, :destroy)).to eq 'group_destroy' } + it { expect(event_name(group_member, :create)).to eq 'user_add_to_group' } + it { expect(event_name(group_member, :destroy)).to eq 'user_remove_from_group' } end def event_data(*args) diff --git a/spec/services/test_hook_service_spec.rb b/spec/services/test_hook_service_spec.rb index 76af5bf7b88..d2b505f55a2 100644 --- a/spec/services/test_hook_service_spec.rb +++ b/spec/services/test_hook_service_spec.rb @@ -8,7 +8,7 @@ describe TestHookService do describe :execute do it "should execute successfully" do stub_request(:post, hook.url).to_return(status: 200) - TestHookService.new.execute(hook, user).should be_true + expect(TestHookService.new.execute(hook, user)).to be_truthy end end end diff --git a/spec/services/update_snippet_service_spec.rb b/spec/services/update_snippet_service_spec.rb new file mode 100644 index 00000000000..841ef9bfed1 --- /dev/null +++ b/spec/services/update_snippet_service_spec.rb @@ -0,0 +1,52 @@ +require 'spec_helper' + +describe UpdateSnippetService do + before do + @user = create :user + @admin = create :user, admin: true + @opts = { + title: 'Test snippet', + file_name: 'snippet.rb', + content: 'puts "hello world"', + visibility_level: Gitlab::VisibilityLevel::PRIVATE + } + end + + context 'When public visibility is restricted' do + before do + allow_any_instance_of(ApplicationSetting).to( + receive(:restricted_visibility_levels).and_return( + [Gitlab::VisibilityLevel::PUBLIC] + ) + ) + + @snippet = create_snippet(@project, @user, @opts) + @opts.merge!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end + + it 'non-admins should not be able to update to public visibility' do + old_visibility = @snippet.visibility_level + update_snippet(@project, @user, @snippet, @opts) + expect(@snippet.errors.messages).to have_key(:visibility_level) + expect(@snippet.errors.messages[:visibility_level].first).to( + match('Public visibility has been restricted') + ) + expect(@snippet.visibility_level).to eq(old_visibility) + end + + it 'admins should be able to update to pubic visibility' do + old_visibility = @snippet.visibility_level + update_snippet(@project, @admin, @snippet, @opts) + expect(@snippet.visibility_level).not_to eq(old_visibility) + expect(@snippet.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC) + end + end + + def create_snippet(project, user, opts) + CreateSnippetService.new(project, user, opts).execute + end + + def update_snippet(project = nil, user, snippet, opts) + UpdateSnippetService.new(project, user, snippet, opts).execute + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 773de6628b1..eaec2198dc8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -37,6 +37,8 @@ RSpec.configure do |config| config.include Devise::TestHelpers, type: :controller config.include TestEnv + config.infer_spec_type_from_file_location! + config.raise_errors_for_deprecations! config.before(:suite) do TestEnv.init diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index d2d532d9738..cca7652093a 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -36,4 +36,15 @@ RSpec.configure do |config| config.after(:each) do DatabaseCleaner.clean end + + # rspec-rails 3 will no longer automatically infer an example group's spec type + # from the file location. You can explicitly opt-in to the feature using this + # config option. + # To explicitly tag specs without using automatic inference, set the `:type` + # metadata manually: + # + # describe ThingsController, :type => :controller do + # # Equivalent to being in spec/controllers + # end + config.infer_spec_type_from_file_location! end diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/mentionable_shared_examples.rb index 692834c9f29..305592fa5a6 100644 --- a/spec/support/mentionable_shared_examples.rb +++ b/spec/support/mentionable_shared_examples.rb @@ -30,16 +30,16 @@ def common_mentionable_setup "!#{mentioned_mr.iid}, " + "#{ext_proj.path_with_namespace}##{ext_issue.iid}, " + "#{ext_proj.path_with_namespace}!#{ext_mr.iid}, " + - "#{ext_proj.path_with_namespace}@#{ext_commit.id[0..5]}, " + - "#{mentioned_commit.sha[0..5]} and itself as #{backref_text}" + "#{ext_proj.path_with_namespace}@#{ext_commit.short_id}, " + + "#{mentioned_commit.sha[0..10]} and itself as #{backref_text}" end before do # Wire the project's repository to return the mentioned commit, and +nil+ for any # unrecognized commits. - commitmap = { '123456' => mentioned_commit } - extra_commits.each { |c| commitmap[c.sha[0..5]] = c } - mproject.repository.stub(:commit) { |sha| commitmap[sha] } + commitmap = { '1234567890a' => mentioned_commit } + extra_commits.each { |c| commitmap[c.short_id] = c } + allow(mproject.repository).to receive(:commit) { |sha| commitmap[sha] } set_mentionable_text.call(ref_string) end end @@ -48,20 +48,19 @@ shared_examples 'a mentionable' do common_mentionable_setup it 'generates a descriptive back-reference' do - subject.gfm_reference.should == backref_text + expect(subject.gfm_reference).to eq(backref_text) end it "extracts references from its reference property" do # De-duplicate and omit itself refs = subject.references(mproject) - - refs.should have(6).items - refs.should include(mentioned_issue) - refs.should include(mentioned_mr) - refs.should include(mentioned_commit) - refs.should include(ext_issue) - refs.should include(ext_mr) - refs.should include(ext_commit) + expect(refs.size).to eq(6) + expect(refs).to include(mentioned_issue) + expect(refs).to include(mentioned_mr) + expect(refs).to include(mentioned_commit) + expect(refs).to include(ext_issue) + expect(refs).to include(ext_mr) + expect(refs).to include(ext_commit) end it 'creates cross-reference notes' do @@ -69,7 +68,7 @@ shared_examples 'a mentionable' do ext_issue, ext_mr, ext_commit] mentioned_objects.each do |referenced| - Note.should_receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject) + expect(Note).to receive(:create_cross_reference_note).with(referenced, subject.local_reference, mauthor, mproject) end subject.create_cross_references!(mproject, mauthor) @@ -78,8 +77,8 @@ shared_examples 'a mentionable' do it 'detects existing cross-references' do Note.create_cross_reference_note(mentioned_issue, subject.local_reference, mauthor, mproject) - subject.has_mentioned?(mentioned_issue).should be_true - subject.has_mentioned?(mentioned_mr).should be_false + expect(subject.has_mentioned?(mentioned_issue)).to be_truthy + expect(subject.has_mentioned?(mentioned_mr)).to be_falsey end end @@ -90,18 +89,18 @@ shared_examples 'an editable mentionable' do it 'creates new cross-reference notes when the mentionable text is edited' do new_text = "still mentions ##{mentioned_issue.iid}, " + - "#{mentioned_commit.sha[0..5]}, " + + "#{mentioned_commit.sha[0..10]}, " + "#{ext_issue.iid}, " + "new refs: ##{other_issue.iid}, " + "#{ext_proj.path_with_namespace}##{other_ext_issue.iid}" [mentioned_issue, mentioned_commit, ext_issue].each do |oldref| - Note.should_not_receive(:create_cross_reference_note).with(oldref, subject.local_reference, + expect(Note).not_to receive(:create_cross_reference_note).with(oldref, subject.local_reference, mauthor, mproject) end [other_issue, other_ext_issue].each do |newref| - Note.should_receive(:create_cross_reference_note).with( + expect(Note).to receive(:create_cross_reference_note).with( newref, subject.local_reference, mauthor, diff --git a/spec/support/repo_helpers.rb b/spec/support/repo_helpers.rb index 4c4775da692..aadf791bf3f 100644 --- a/spec/support/repo_helpers.rb +++ b/spec/support/repo_helpers.rb @@ -43,6 +43,25 @@ eos ) end + def another_sample_commit + OpenStruct.new( + id: "e56497bb5f03a90a51293fc6d516788730953899", + parent_id: '4cd80ccab63c82b4bad16faa5193fbd2aa06df40', + author_full_name: "Sytse Sijbrandij", + author_email: "sytse@gitlab.com", + files_changed_count: 1, + message: <<eos +Add directory structure for tree_helper spec + +This directory structure is needed for a testing the method flatten_tree(tree) in the TreeHelper module + +See [merge request #275](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/275#note_732774) + +See merge request !2 +eos + ) + end + def sample_big_commit OpenStruct.new( id: "913c66a37b4a45b9769037c55c2d238bd0942d2e", diff --git a/spec/support/taskable_shared_examples.rb b/spec/support/taskable_shared_examples.rb index 42252675683..490f453d468 100644 --- a/spec/support/taskable_shared_examples.rb +++ b/spec/support/taskable_shared_examples.rb @@ -34,9 +34,9 @@ EOT end it 'knows if it has tasks' do - expect(subject.tasks?).to be_true + expect(subject.tasks?).to be_truthy subject.description = 'Now I have no tasks' - expect(subject.tasks?).to be_false + expect(subject.tasks?).to be_falsey end end diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb index 5f55871dc4a..f869488d8d8 100644 --- a/spec/support/test_env.rb +++ b/spec/support/test_env.rb @@ -3,28 +3,28 @@ require 'rspec/mocks' module TestEnv extend self + # When developing the seed repository, comment out the branch you will modify. + BRANCH_SHA = { + 'flatten-dir' => 'e56497b', + 'feature' => '0b4bc9a', + 'feature_conflict' => 'bb5206f', + 'fix' => '12d65c8', + 'improve/awesome' => '5937ac0', + 'markdown' => '0ed8c6c', + 'master' => '5937ac0' + } + # Test environment # # See gitlab.yml.example test section for paths # def init(opts = {}) - RSpec::Mocks::setup(self) - # Disable mailer for spinach tests disable_mailer if opts[:mailer] == false - # Clean /tmp/tests - tmp_test_path = Rails.root.join('tmp', 'tests') - - if File.directory?(tmp_test_path) - Dir.entries(tmp_test_path).each do |entry| - unless ['.', '..', 'gitlab-shell'].include?(entry) - FileUtils.rm_r(File.join(tmp_test_path, entry)) - end - end - end + clean_test_path - FileUtils.mkdir_p(tmp_test_path) + FileUtils.mkdir_p(repos_path) # Setup GitLab shell for test instance setup_gitlab_shell @@ -38,24 +38,58 @@ module TestEnv end def enable_mailer - NotificationService.any_instance.unstub(:mailer) + allow_any_instance_of(NotificationService).to receive(:mailer).and_call_original + end + + # Clean /tmp/tests + # + # Keeps gitlab-shell and gitlab-test + def clean_test_path + tmp_test_path = Rails.root.join('tmp', 'tests', '**') + + Dir[tmp_test_path].each do |entry| + unless File.basename(entry) =~ /\Agitlab-(shell|test)\z/ + FileUtils.rm_rf(entry) + end + end end def setup_gitlab_shell - `rake gitlab:shell:install` + unless File.directory?(Rails.root.join(*%w(tmp tests gitlab-shell))) + `rake gitlab:shell:install` + end end def setup_factory_repo clone_url = "https://gitlab.com/gitlab-org/#{factory_repo_name}.git" unless File.directory?(factory_repo_path) - git_cmd = %W(git clone --bare #{clone_url} #{factory_repo_path}) - system(*git_cmd) + system(*%W(git clone -q #{clone_url} #{factory_repo_path})) + end + + Dir.chdir(factory_repo_path) do + BRANCH_SHA.each do |branch, sha| + # Try to reset without fetching to avoid using the network. + reset = %W(git update-ref refs/heads/#{branch} #{sha}) + unless system(*reset) + if system(*%w(git fetch origin)) + unless system(*reset) + raise 'The fetched test seed '\ + 'does not contain the required revision.' + end + else + raise 'Could not fetch test seed repository.' + end + end + end end + + # We must copy bare repositories because we will push to them. + system(*%W(git clone -q --bare #{factory_repo_path} #{factory_repo_path_bare})) end def copy_repo(project) - base_repo_path = File.expand_path(factory_repo_path) + base_repo_path = File.expand_path(factory_repo_path_bare) target_repo_path = File.expand_path(repos_path + "/#{project.namespace.path}/#{project.path}.git") FileUtils.mkdir_p(target_repo_path) FileUtils.cp_r("#{base_repo_path}/.", target_repo_path) @@ -69,7 +103,11 @@ module TestEnv private def factory_repo_path - @factory_repo_path ||= repos_path + "/root/#{factory_repo_name}.git" + @factory_repo_path ||= Rails.root.join('tmp', 'tests', factory_repo_name) + end + + def factory_repo_path_bare + "#{factory_repo_path}_bare" end def factory_repo_name diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb index 71a45eb2fa6..60942cc95fc 100644 --- a/spec/tasks/gitlab/backup_rake_spec.rb +++ b/spec/tasks/gitlab/backup_rake_spec.rb @@ -13,7 +13,7 @@ describe 'gitlab:app namespace rake task' do describe 'backup_restore' do before do # avoid writing task output to spec progress - $stdout.stub :write + allow($stdout).to receive :write end let :run_rake_task do @@ -24,7 +24,7 @@ describe 'gitlab:app namespace rake task' do context 'gitlab version' do before do Dir.stub glob: [] - Dir.stub :chdir + allow(Dir).to receive :chdir File.stub exists?: true Kernel.stub system: true FileUtils.stub cp_r: true @@ -41,9 +41,9 @@ describe 'gitlab:app namespace rake task' do it 'should invoke restoration on mach' do YAML.stub load_file: {gitlab_version: gitlab_version} - Rake::Task["gitlab:backup:db:restore"].should_receive :invoke - Rake::Task["gitlab:backup:repo:restore"].should_receive :invoke - Rake::Task["gitlab:shell:setup"].should_receive :invoke + expect(Rake::Task["gitlab:backup:db:restore"]).to receive :invoke + expect(Rake::Task["gitlab:backup:repo:restore"]).to receive :invoke + expect(Rake::Task["gitlab:shell:setup"]).to receive :invoke expect { run_rake_task }.to_not raise_error end end diff --git a/spec/tasks/gitlab/mail_google_schema_whitelisting.rb b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb new file mode 100644 index 00000000000..22e746870dc --- /dev/null +++ b/spec/tasks/gitlab/mail_google_schema_whitelisting.rb @@ -0,0 +1,27 @@ +require 'spec_helper' +require 'rake' + +describe 'gitlab:mail_google_schema_whitelisting rake task' do + before :all do + Rake.application.rake_require "tasks/gitlab/task_helpers" + Rake.application.rake_require "tasks/gitlab/mail_google_schema_whitelisting" + # empty task as env is already loaded + Rake::Task.define_task :environment + end + + describe 'call' do + before do + # avoid writing task output to spec progress + allow($stdout).to receive :write + end + + let :run_rake_task do + Rake::Task["gitlab:mail_google_schema_whitelisting"].reenable + Rake.application.invoke_task "gitlab:mail_google_schema_whitelisting" + end + + it 'should run the task without errors' do + expect { run_rake_task }.to_not raise_error + end + end +end diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index 4273fd1019a..df1a2b84a53 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -1,9 +1,13 @@ require 'spec_helper' describe PostReceive do + let(:changes) { "123456 789012 refs/heads/tést\n654321 210987 refs/tags/tag" } + let(:wrongly_encoded_changes) { changes.encode("ISO-8859-1").force_encoding("UTF-8") } + let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) } + context "as a resque worker" do it "reponds to #perform" do - PostReceive.new.should respond_to(:perform) + expect(PostReceive.new).to respond_to(:perform) end end @@ -13,33 +17,29 @@ describe PostReceive do let(:key_id) { key.shell_id } it "fetches the correct project" do - Project.should_receive(:find_with_namespace).with(project.path_with_namespace).and_return(project) - PostReceive.new.perform(pwd(project), key_id, changes) + expect(Project).to receive(:find_with_namespace).with(project.path_with_namespace).and_return(project) + PostReceive.new.perform(pwd(project), key_id, base64_changes) end it "does not run if the author is not in the project" do - Key.stub(:find_by).with(hash_including(id: anything())) { nil } + allow(Key).to receive(:find_by).with(hash_including(id: anything())) { nil } - project.should_not_receive(:execute_hooks) + expect(project).not_to receive(:execute_hooks) - PostReceive.new.perform(pwd(project), key_id, changes).should be_false + expect(PostReceive.new.perform(pwd(project), key_id, base64_changes)).to be_falsey end it "asks the project to trigger all hooks" do Project.stub(find_with_namespace: project) - project.should_receive(:execute_hooks) - project.should_receive(:execute_services) - project.should_receive(:update_merge_requests) + expect(project).to receive(:execute_hooks).twice + expect(project).to receive(:execute_services).twice + expect(project).to receive(:update_merge_requests) - PostReceive.new.perform(pwd(project), key_id, changes) + PostReceive.new.perform(pwd(project), key_id, base64_changes) end end def pwd(project) File.join(Gitlab.config.gitlab_shell.repos_path, project.path_with_namespace) end - - def changes - 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master' - end end |