diff options
Diffstat (limited to 'spec/requests/ci/api')
-rw-r--r-- | spec/requests/ci/api/builds_spec.rb | 115 | ||||
-rw-r--r-- | spec/requests/ci/api/commits_spec.rb | 65 | ||||
-rw-r--r-- | spec/requests/ci/api/forks_spec.rb | 60 | ||||
-rw-r--r-- | spec/requests/ci/api/projects_spec.rb | 251 | ||||
-rw-r--r-- | spec/requests/ci/api/runners_spec.rb | 83 | ||||
-rw-r--r-- | spec/requests/ci/api/triggers_spec.rb | 78 |
6 files changed, 652 insertions, 0 deletions
diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb new file mode 100644 index 00000000000..7da212da83a --- /dev/null +++ b/spec/requests/ci/api/builds_spec.rb @@ -0,0 +1,115 @@ +require 'spec_helper' + +describe Ci::API::API do + include ApiHelpers + + let(:runner) { FactoryGirl.create(:runner, tag_list: ["mysql", "ruby"]) } + let(:project) { FactoryGirl.create(:project) } + + describe "Builds API for runners" do + let(:shared_runner) { FactoryGirl.create(:runner, token: "SharedRunner") } + let(:shared_project) { FactoryGirl.create(:project, name: "SharedProject") } + + before do + FactoryGirl.create :runner_project, project_id: project.id, runner_id: runner.id + end + + describe "POST /builds/register" do + it "should start a build" do + commit = FactoryGirl.create(:commit, project: project) + commit.create_builds + build = commit.builds.first + + post api("/builds/register"), token: runner.token, info: {platform: :darwin} + + response.status.should == 201 + json_response['sha'].should == build.sha + runner.reload.platform.should == "darwin" + end + + it "should return 404 error if no pending build found" do + post api("/builds/register"), token: runner.token + + response.status.should == 404 + end + + it "should return 404 error if no builds for specific runner" do + commit = FactoryGirl.create(:commit, project: shared_project) + FactoryGirl.create(:build, commit: commit, status: 'pending' ) + + post api("/builds/register"), token: runner.token + + response.status.should == 404 + end + + it "should return 404 error if no builds for shared runner" do + commit = FactoryGirl.create(:commit, project: project) + FactoryGirl.create(:build, commit: commit, status: 'pending' ) + + post api("/builds/register"), token: shared_runner.token + + response.status.should == 404 + end + + it "returns options" do + commit = FactoryGirl.create(:commit, project: project) + commit.create_builds + + post api("/builds/register"), token: runner.token, info: {platform: :darwin} + + response.status.should == 201 + json_response["options"].should == {"image" => "ruby:2.1", "services" => ["postgres"]} + end + + it "returns variables" do + commit = FactoryGirl.create(:commit, project: project) + commit.create_builds + project.variables << Variable.new(key: "SECRET_KEY", value: "secret_value") + + post api("/builds/register"), token: runner.token, info: {platform: :darwin} + + response.status.should == 201 + json_response["variables"].should == [ + {"key" => "DB_NAME", "value" => "postgres", "public" => true}, + {"key" => "SECRET_KEY", "value" => "secret_value", "public" => false}, + ] + end + + it "returns variables for triggers" do + trigger = FactoryGirl.create(:trigger, project: project) + commit = FactoryGirl.create(:commit, project: project) + + trigger_request = FactoryGirl.create(:trigger_request_with_variables, commit: commit, trigger: trigger) + commit.create_builds(trigger_request) + project.variables << Variable.new(key: "SECRET_KEY", value: "secret_value") + + post api("/builds/register"), token: runner.token, info: {platform: :darwin} + + response.status.should == 201 + json_response["variables"].should == [ + {"key" => "DB_NAME", "value" => "postgres", "public" => true}, + {"key" => "SECRET_KEY", "value" => "secret_value", "public" => false}, + {"key" => "TRIGGER_KEY", "value" => "TRIGGER_VALUE", "public" => false}, + ] + end + end + + describe "PUT /builds/:id" do + let(:commit) { FactoryGirl.create(:commit, project: project)} + let(:build) { FactoryGirl.create(:build, commit: commit, runner_id: runner.id) } + + it "should update a running build" do + build.run! + put api("/builds/#{build.id}"), token: runner.token + response.status.should == 200 + end + + it 'Should not override trace information when no trace is given' do + build.run! + build.update!(trace: 'hello_world') + put api("/builds/#{build.id}"), token: runner.token + expect(build.reload.trace).to eq 'hello_world' + end + end + end +end diff --git a/spec/requests/ci/api/commits_spec.rb b/spec/requests/ci/api/commits_spec.rb new file mode 100644 index 00000000000..99021dd681d --- /dev/null +++ b/spec/requests/ci/api/commits_spec.rb @@ -0,0 +1,65 @@ +require 'spec_helper' + +describe Ci::API::API, 'Commits' do + include ApiHelpers + + let(:project) { FactoryGirl.create(:project) } + let(:commit) { FactoryGirl.create(:commit, project: project) } + + let(:options) { + { + project_token: project.token, + project_id: project.id + } + } + + describe "GET /commits" do + before { commit } + + it "should return commits per project" do + get api("/commits"), options + + response.status.should == 200 + json_response.count.should == 1 + json_response.first["project_id"].should == project.id + json_response.first["sha"].should == commit.sha + end + end + + describe "POST /commits" do + let(:data) { + { + "before" => "95790bf891e76fee5e1747ab589903a6a1f80f22", + "after" => "da1560886d4f094c3e6c9ef40349f7d38b5d27d7", + "ref" => "refs/heads/master", + "commits" => [ + { + "id" => "b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", + "message" => "Update Catalan translation to e38cb41.", + "timestamp" => "2011-12-12T14:27:31+02:00", + "url" => "http://localhost/diaspora/commits/b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327", + "author" => { + "name" => "Jordi Mallach", + "email" => "jordi@softcatala.org", + } + } + ], + ci_yaml_file: gitlab_ci_yaml + } + } + + it "should create a build" do + post api("/commits"), options.merge(data: data) + + response.status.should == 201 + json_response['sha'].should == "da1560886d4f094c3e6c9ef40349f7d38b5d27d7" + end + + it "should return 400 error if no data passed" do + post api("/commits"), options + + response.status.should == 400 + json_response['message'].should == "400 (Bad request) \"data\" not given" + end + end +end diff --git a/spec/requests/ci/api/forks_spec.rb b/spec/requests/ci/api/forks_spec.rb new file mode 100644 index 00000000000..74efc0c30be --- /dev/null +++ b/spec/requests/ci/api/forks_spec.rb @@ -0,0 +1,60 @@ +require 'spec_helper' + +describe Ci::API::API do + include ApiHelpers + + let(:project) { FactoryGirl.create(:project) } + let(:gitlab_url) { GitlabCi.config.gitlab_server.url } + let(:private_token) { Network.new.authenticate(access_token: "some_token")["private_token"] } + + let(:options) { + { + private_token: private_token, + url: gitlab_url + } + } + + before { + stub_gitlab_calls + } + + + describe "POST /forks" do + let(:project_info) { + { + project_id: project.gitlab_id, + project_token: project.token, + data: { + id: 2, + name_with_namespace: "Gitlab.org / Underscore", + path_with_namespace: "gitlab-org/underscore", + default_branch: "master", + ssh_url_to_repo: "git@example.com:gitlab-org/underscore" + } + } + } + + context "with valid info" do + before do + options.merge!(project_info) + end + + it "should create a project with valid data" do + post api("/forks"), options + response.status.should == 201 + json_response['name'].should == "Gitlab.org / Underscore" + end + end + + context "with invalid project info" do + before do + options.merge!({}) + end + + it "should error with invalid data" do + post api("/forks"), options + response.status.should == 400 + end + end + end +end diff --git a/spec/requests/ci/api/projects_spec.rb b/spec/requests/ci/api/projects_spec.rb new file mode 100644 index 00000000000..65cfc909b48 --- /dev/null +++ b/spec/requests/ci/api/projects_spec.rb @@ -0,0 +1,251 @@ +require 'spec_helper' + +describe Ci::API::API do + include ApiHelpers + + let(:gitlab_url) { GitlabCi.config.gitlab_server.url } + let(:private_token) { Network.new.authenticate(access_token: "some_token")["private_token"] } + + let(:options) { + { + private_token: private_token, + url: gitlab_url + } + } + + before { + stub_gitlab_calls + } + + context "requests for scoped projects" do + # NOTE: These ids are tied to the actual projects on demo.gitlab.com + describe "GET /projects" do + let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) } + let!(:project2) { FactoryGirl.create(:project, name: "gitlab-ci", gitlab_id: 4) } + + it "should return all projects on the CI instance" do + get api("/projects"), options + response.status.should == 200 + json_response.count.should == 2 + json_response.first["id"].should == project1.id + json_response.last["id"].should == project2.id + end + end + + describe "GET /projects/owned" do + # NOTE: This user doesn't own any of these projects on demo.gitlab.com + let!(:project1) { FactoryGirl.create(:project, name: "gitlabhq", gitlab_id: 3) } + let!(:project2) { FactoryGirl.create(:project, name: "random-project", gitlab_id: 9898) } + + it "should return all projects on the CI instance" do + get api("/projects/owned"), options + + response.status.should == 200 + json_response.count.should == 0 + end + end + end + + describe "POST /projects/:project_id/webhooks" do + let!(:project) { FactoryGirl.create(:project) } + + context "Valid Webhook URL" do + let!(:webhook) { {web_hook: "http://example.com/sth/1/ala_ma_kota" } } + + before do + options.merge!(webhook) + end + + it "should create webhook for specified project" do + post api("/projects/#{project.id}/webhooks"), options + response.status.should == 201 + json_response["url"].should == webhook[:web_hook] + end + + it "fails to create webhook for non existsing project" do + post api("/projects/non-existant-id/webhooks"), options + response.status.should == 404 + end + + it "non-manager is not authorized" do + User.any_instance.stub(:can_manage_project?).and_return(false) + post api("/projects/#{project.id}/webhooks"), options + response.status.should == 401 + end + end + + context "Invalid Webhook URL" do + let!(:webhook) { {web_hook: "ala_ma_kota" } } + + before do + options.merge!(webhook) + end + + it "fails to create webhook for not valid url" do + post api("/projects/#{project.id}/webhooks"), options + response.status.should == 400 + end + end + + context "Missed web_hook parameter" do + it "fails to create webhook for not provided url" do + post api("/projects/#{project.id}/webhooks"), options + response.status.should == 400 + end + end + end + + describe "GET /projects/:id" do + let!(:project) { FactoryGirl.create(:project) } + + context "with an existing project" do + it "should retrieve the project info" do + get api("/projects/#{project.id}"), options + response.status.should == 200 + json_response['id'].should == project.id + end + end + + context "with a non-existing project" do + it "should return 404 error if project not found" do + get api("/projects/non_existent_id"), options + response.status.should == 404 + end + end + end + + describe "PUT /projects/:id" do + let!(:project) { FactoryGirl.create(:project) } + let!(:project_info) { {name: "An updated name!" } } + + before do + options.merge!(project_info) + end + + it "should update a specific project's information" do + put api("/projects/#{project.id}"), options + response.status.should == 200 + json_response["name"].should == project_info[:name] + end + + it "fails to update a non-existing project" do + put api("/projects/non-existant-id"), options + response.status.should == 404 + end + + it "non-manager is not authorized" do + User.any_instance.stub(:can_manage_project?).and_return(false) + put api("/projects/#{project.id}"), options + response.status.should == 401 + end + end + + describe "DELETE /projects/:id" do + let!(:project) { FactoryGirl.create(:project) } + + it "should delete a specific project" do + delete api("/projects/#{project.id}"), options + response.status.should == 200 + + expect { project.reload }.to raise_error + end + + it "non-manager is not authorized" do + User.any_instance.stub(:can_manage_project?).and_return(false) + delete api("/projects/#{project.id}"), options + response.status.should == 401 + end + + it "is getting not found error" do + delete api("/projects/not-existing_id"), options + response.status.should == 404 + end + end + + describe "POST /projects" do + let(:project_info) { + { + name: "My project", + gitlab_id: 1, + path: "testing/testing", + ssh_url_to_repo: "ssh://example.com/testing/testing.git" + } + } + + let(:invalid_project_info) { {} } + + context "with valid project info" do + before do + options.merge!(project_info) + end + + it "should create a project with valid data" do + post api("/projects"), options + response.status.should == 201 + json_response['name'].should == project_info[:name] + end + end + + context "with invalid project info" do + before do + options.merge!(invalid_project_info) + end + + it "should error with invalid data" do + post api("/projects"), options + response.status.should == 400 + end + end + + describe "POST /projects/:id/runners/:id" do + let(:project) { FactoryGirl.create(:project) } + let(:runner) { FactoryGirl.create(:runner) } + + it "should add the project to the runner" do + post api("/projects/#{project.id}/runners/#{runner.id}"), options + response.status.should == 201 + + project.reload + project.runners.first.id.should == runner.id + end + + it "should fail if it tries to link a non-existing project or runner" do + post api("/projects/#{project.id}/runners/non-existing"), options + response.status.should == 404 + + post api("/projects/non-existing/runners/#{runner.id}"), options + response.status.should == 404 + end + + it "non-manager is not authorized" do + User.any_instance.stub(:can_manage_project?).and_return(false) + post api("/projects/#{project.id}/runners/#{runner.id}"), options + response.status.should == 401 + end + end + + describe "DELETE /projects/:id/runners/:id" do + let(:project) { FactoryGirl.create(:project) } + let(:runner) { FactoryGirl.create(:runner) } + + before do + post api("/projects/#{project.id}/runners/#{runner.id}"), options + end + + it "should remove the project from the runner" do + project.runners.should be_present + delete api("/projects/#{project.id}/runners/#{runner.id}"), options + response.status.should == 200 + + project.reload + project.runners.should be_empty + end + + it "non-manager is not authorized" do + User.any_instance.stub(:can_manage_project?).and_return(false) + post api("/projects/#{project.id}/runners/#{runner.id}"), options + response.status.should == 401 + end + end + end +end diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb new file mode 100644 index 00000000000..3faebd40bae --- /dev/null +++ b/spec/requests/ci/api/runners_spec.rb @@ -0,0 +1,83 @@ +require 'spec_helper' + +describe Ci::API::API do + include ApiHelpers + include StubGitlabCalls + + before { + stub_gitlab_calls + } + + describe "GET /runners" do + let(:gitlab_url) { GitlabCi.config.gitlab_server.url } + let(:private_token) { Network.new.authenticate(access_token: "some_token")["private_token"] } + let(:options) { + { + :private_token => private_token, + :url => gitlab_url + } + } + + before do + 5.times { FactoryGirl.create(:runner) } + end + + it "should retrieve a list of all runners" do + get api("/runners"), options + response.status.should == 200 + json_response.count.should == 5 + json_response.last.should have_key("id") + json_response.last.should have_key("token") + end + end + + describe "POST /runners/register" do + describe "should create a runner if token provided" do + before { post api("/runners/register"), token: GitlabCi::REGISTRATION_TOKEN } + + it { response.status.should == 201 } + end + + describe "should create a runner with description" do + before { post api("/runners/register"), token: GitlabCi::REGISTRATION_TOKEN, description: "server.hostname" } + + it { response.status.should == 201 } + it { Runner.first.description.should == "server.hostname" } + end + + describe "should create a runner with tags" do + before { post api("/runners/register"), token: GitlabCi::REGISTRATION_TOKEN, tag_list: "tag1, tag2" } + + it { response.status.should == 201 } + it { Runner.first.tag_list.sort.should == ["tag1", "tag2"] } + end + + describe "should create a runner if project token provided" do + let(:project) { FactoryGirl.create(:project) } + before { post api("/runners/register"), token: project.token } + + it { response.status.should == 201 } + it { project.runners.size.should == 1 } + end + + it "should return 403 error if token is invalid" do + post api("/runners/register"), token: 'invalid' + + response.status.should == 403 + end + + it "should return 400 error if no token" do + post api("/runners/register") + + response.status.should == 400 + end + end + + describe "DELETE /runners/delete" do + let!(:runner) { FactoryGirl.create(:runner) } + before { delete api("/runners/delete"), token: runner.token } + + it { response.status.should == 200 } + it { Runner.count.should == 0 } + end +end diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb new file mode 100644 index 00000000000..5da40a69991 --- /dev/null +++ b/spec/requests/ci/api/triggers_spec.rb @@ -0,0 +1,78 @@ +require 'spec_helper' + +describe Ci::API::API do + include ApiHelpers + + describe 'POST /projects/:project_id/refs/:ref/trigger' do + let!(:trigger_token) { 'secure token' } + let!(:project) { FactoryGirl.create(:project) } + let!(:project2) { FactoryGirl.create(:project) } + let!(:trigger) { FactoryGirl.create(:trigger, project: project, token: trigger_token) } + let(:options) { + { + token: trigger_token + } + } + + context 'Handles errors' do + it 'should return bad request if token is missing' do + post api("/projects/#{project.id}/refs/master/trigger") + response.status.should == 400 + end + + it 'should return not found if project is not found' do + post api('/projects/0/refs/master/trigger'), options + response.status.should == 404 + end + + it 'should return unauthorized if token is for different project' do + post api("/projects/#{project2.id}/refs/master/trigger"), options + response.status.should == 401 + end + end + + context 'Have a commit' do + before do + @commit = FactoryGirl.create(:commit, project: project) + end + + it 'should create builds' do + post api("/projects/#{project.id}/refs/master/trigger"), options + response.status.should == 201 + @commit.builds.reload + @commit.builds.size.should == 2 + end + + it 'should return bad request with no builds created if there\'s no commit for that ref' do + post api("/projects/#{project.id}/refs/other-branch/trigger"), options + response.status.should == 400 + json_response['message'].should == 'No builds created' + end + + context 'Validates variables' do + let(:variables) { + {'TRIGGER_KEY' => 'TRIGGER_VALUE'} + } + + it 'should validate variables to be a hash' do + post api("/projects/#{project.id}/refs/master/trigger"), options.merge(variables: 'value') + response.status.should == 400 + json_response['message'].should == 'variables needs to be a hash' + end + + it 'should validate variables needs to be a map of key-valued strings' do + post api("/projects/#{project.id}/refs/master/trigger"), options.merge(variables: {key: %w(1 2)}) + response.status.should == 400 + json_response['message'].should == 'variables needs to be a map of key-valued strings' + end + + it 'create trigger request with variables' do + post api("/projects/#{project.id}/refs/master/trigger"), options.merge(variables: variables) + response.status.should == 201 + @commit.builds.reload + @commit.builds.first.trigger_request.variables.should == variables + end + end + end + end +end |