diff --git a/lib/api.rb b/lib/api.rb index 3ff3b383..be04701c 100644 --- a/lib/api.rb +++ b/lib/api.rb @@ -16,5 +16,6 @@ module Gitlab mount Users mount Projects mount Issues + mount Milestones end end diff --git a/lib/api/milestones.rb b/lib/api/milestones.rb new file mode 100644 index 00000000..3cdb7d9f --- /dev/null +++ b/lib/api/milestones.rb @@ -0,0 +1,93 @@ +module Gitlab + # Milestones API + class Milestones < Grape::API + before { authenticate! } + + resource :projects do + # Get a list of project milestones + # + # Parameters: + # id (required) - The ID or code name of a project + # Example Request: + # GET /projects/:id/milestones + get ":id/milestones" do + present user_project.milestones, with: Entities::Milestone + end + + # Get a single project milestone + # + # Parameters: + # id (required) - The ID or code name of a project + # milestone_id (required) - The ID of a project milestone + # Example Request: + # GET /projects/:id/milestones/:milestone_id + get ":id/milestones/:milestone_id" do + @milestone = user_project.milestones.find(params[:milestone_id]) + present @milestone, with: Entities::Milestone + end + + # Create a new project milestone + # + # Parameters: + # id (required) - The ID or code name of the project + # title (required) - The title of the milestone + # description (optional) - The description of the milestone + # due_date (optional) - The due date of the milestone + # closed (optional) - The status of the milestone + # Example Request: + # POST /projects/:id/milestones + post ":id/milestones" do + @milestone = user_project.milestones.new( + title: params[:title], + description: params[:description], + due_date: params[:due_date], + closed: (params[:closed] || false) + ) + + if @milestone.save + present @milestone, with: Entities::Milestone + else + error!({'message' => '404 Not found'}, 404) + end + end + + # Update an existing project milestone + # + # Parameters: + # id (required) - The ID or code name of a project + # title (optional) - The title of a milestone + # description (optional) - The description of a milestone + # due_date (optional) - The due date of a milestone + # closed (optional) - The status of the milestone + # Example Request: + # PUT /projects/:id/milestones/:milestone_id + put ":id/milestones/:milestone_id" do + @milestone = user_project.milestones.find(params[:milestone_id]) + parameters = { + title: (params[:title] || @milestone.title), + description: (params[:description] || @milestone.description), + due_date: (params[:due_date] || @milestone.due_date), + closed: (params[:closed] || @milestone.closed) + } + + if @milestone.update_attributes(parameters) + present @milestone, with: Entities::Milestone + else + error!({'message' => '404 Not found'}, 404) + end + end + + # Delete a project milestone + # + # Parameters: + # id (required) - The ID or code name of a project + # milestone_id (required) - The ID of a project milestone + # Example Request: + # DELETE /projects/:id/milestones/:milestone_id + delete ":id/milestones/:milestone_id" do + @milestone = user_project.milestones.find(params[:milestone_id]) + @milestone.destroy + end + end + end +end diff --git a/spec/api/milestones_spec.rb b/spec/api/milestones_spec.rb new file mode 100644 index 00000000..23f19ddd --- /dev/null +++ b/spec/api/milestones_spec.rb @@ -0,0 +1,53 @@ +require 'spec_helper' + +describe Gitlab::API do + let(:user) { Factory :user } + let!(:project) { Factory :project, owner: user } + let!(:milestone) { Factory :milestone, project: project } + + before { project.add_access(user, :read) } + + describe "GET /projects/:id/milestones" do + it "should return project milestones" do + get "#{api_prefix}/projects/#{project.code}/milestones?private_token=#{user.private_token}" + response.status.should == 200 + json_response.should be_an Array + json_response.first['title'].should == milestone.title + end + end + + describe "GET /projects/:id/milestones/:milestone_id" do + it "should return a project milestone by id" do + get "#{api_prefix}/projects/#{project.code}/milestones/#{milestone.id}?private_token=#{user.private_token}" + response.status.should == 200 + json_response['title'].should == milestone.title + end + end + + describe "POST /projects/:id/milestones" do + it "should create a new project milestone" do + post "#{api_prefix}/projects/#{project.code}/milestones?private_token=#{user.private_token}", + title: 'new milestone' + response.status.should == 201 + json_response['title'].should == 'new milestone' + json_response['description'].should be_nil + end + end + + describe "PUT /projects/:id/milestones/:milestone_id" do + it "should update a project milestone" do + put "#{api_prefix}/projects/#{project.code}/milestones/#{milestone.id}?private_token=#{user.private_token}", + title: 'updated title' + response.status.should == 200 + json_response['title'].should == 'updated title' + end + end + + describe "DELETE /projects/:id/milestones/:milestone_id" do + it "should delete a project milestone" do + expect { + delete "#{api_prefix}/projects/#{project.code}/milestones/#{milestone.id}?private_token=#{user.private_token}" + }.to change { Milestone.count }.by(-1) + end + end +end