Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Projects resource #145

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,25 @@ following = team.following
repos = team.repos
```

#### projects Endpoint

```ruby
# [x] GET the list of team projects
projects = bucket.team('team name').projects

# [x] GET the information about a specific team project
project = projects.find('project key')

# [x] POST (create) a new team project
projects.create(key: 'project key', name: 'project name', description: '...', is_private: true ...)

# [x] PUT (update) a team project
project.update(description: 'New description'...)

# [x] DELETE a team project
project.destroy
```

#### users Endpoint

```ruby
Expand Down
6 changes: 6 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ require 'bundler/setup'

require "bundler/gem_tasks"


desc 'launch an irb console with the gem loaded'
task :console do
exec 'irb -I lib -r tinybucket'
end

desc 'cleanup rcov, doc directories'
task :clean do
rm_rf 'coverage'
Expand Down
12 changes: 12 additions & 0 deletions lib/tinybucket/api/helper/projects_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ def path_to_find(owner, project_key)
[project_key, 'project_key'])
end

def path_to_post(owner)
build_path(base_path(owner), '/')
end

def path_to_put(owner, project_key)
build_path(base_path(owner), [project_key, 'project_key'])
end

def path_to_delete(owner, project_key)
build_path(base_path(owner), [project_key, 'project_key'])
end

def base_path(owner)
build_path('/teams',
[owner, 'owner'],
Expand Down
24 changes: 24 additions & 0 deletions lib/tinybucket/api/projects_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,30 @@ def find(project_key, options = {})
get_parser(:object, Tinybucket::Model::Project)
)
end

def post(options = {})
post_path(
path_to_post(owner),
options,
get_parser(:object, Tinybucket::Model::Project)
)
end

def put(project_key, options = {})
put_path(
path_to_put(owner, project_key),
options,
get_parser(:object, Tinybucket::Model::Project)
)
end

def delete(project_key, options = {})
delete_path(
path_to_delete(owner, project_key),
options,
get_parser(:object, Tinybucket::Model::Project)
)
end
end
end
end
46 changes: 39 additions & 7 deletions lib/tinybucket/model/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,49 @@
module Tinybucket
module Model
class Project < Base
# Project
#
# @see https://developer.atlassian.com/bitbucket/api/2/reference/resource/teams/%7Busername%7D/projects
# projects Endpoint
#
# @!attribute [rw] type
# @return [String]
# @!attribute [rw] description
# @return [String, NilClass]
# @!attribute [rw] links
# @return [Hash]
# @!attribute [rw] uuid
# @return [String]
# @!attribute [rw] created_on
# @return [String]
# @!attribute [rw] key
# @return [String]
# @!attribute [rw] updated_on
# @return [String]
# @!attribute [rw] is_private
# @return [TrueClass, FalseClass]
# @!attribute [rw] name
# @return [String]
# @!attribute [rw] owner
# @return [Hash]
acceptable_attributes \
:type, :description, :links, :uuid, :created_on,
:key, :updated_on, :is_private, :name, :owner

# Update this project
# Update the remote reference and the instance of this project
#
# @param _params [Hash]
# @raise [NotImplementedError] to be implemented
def update(_params)
raise NotImplementedError
# @param options [Hash]
# @return [Tinybucket::Model::Project]
def update(options)
self.attributes = projects_api.put(key, options).attributes
self
end

# Destroy this project
#
# @raise [NotImplementedError] to be implemented.
# @return [NilClass]
def destroy
raise NotImplementedError
projects_api.delete(key)
end

# Get repositories
Expand All @@ -31,6 +57,12 @@ def repos

private

def projects_api
create_api('Projects').tap do |api|
api.owner = owner["username"]
end
end

def owner_name
raise 'This project is not loaded yet.' if (owner.nil? || owner['username'].nil?)
owner['username']
Expand Down
3 changes: 2 additions & 1 deletion lib/tinybucket/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def request(method, path, params, parser, options)
request.url(path, params)
when :post, :put, :patch
request.path = path
request.body = extract_data_from_params(params) unless params.empty?
request.body = extract_data_from_params(params).to_json unless params.empty?
request.headers['Content-Type'] = 'application/json'
else
raise ArgumentError, 'unknown http method: ' + method
end
Expand Down
10 changes: 4 additions & 6 deletions lib/tinybucket/resource/projects.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ def find(project_key, options = {})

# Create a new project
#
# NOTE: Not Implemented yet.
#
# @param _params [Hash]
# @raise [NotImplementedError] to be implemented
def create(_params)
raise NotImplementedError
# @param options [Hash]
# @return [Tinybucket::Model::Project]
def create(options)
projects_api.post(options)
end

private
Expand Down
Empty file.
41 changes: 41 additions & 0 deletions spec/fixtures/teams/test_team/projects/myprj/put.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"uuid": "{45234c3d-efa0-4c2a-be4e-78c1b30a30d0}",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/teams/test_team/projects/myprj"
},
"html": {
"href": "https://bitbucket.org/account/user/test_team/projects/myprj"
},
"repositories": {
"href": "https://api.bitbucket.org/2.0/repositories/test_team?q='project.key=\"myprj\"'"
},
"avatar": {
"href": "https://bitbucket.org/account/user/test_team/projects/myprj/avatar/32"
}
},
"description": null,
"created_on": "2016-03-19T03:34:27.792230+00:00",
"key": "myprj",
"owner": {
"username": "test_team",
"display_name": "test team",
"type": "team",
"uuid": "{e0f17982-efab-43cb-8589-7bacabb37cab}",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/teams/test_team"
},
"html": {
"href": "https://bitbucket.org/test_team/"
},
"avatar": {
"href": "https://bitbucket.org/account/test_team/avatar/32/"
}
}
},
"updated_on": "2016-03-19T03:34:27.792256+00:00",
"type": "project",
"is_private": false,
"name": "New project name"
}
41 changes: 41 additions & 0 deletions spec/fixtures/teams/test_team/projects/post.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"uuid": "{45234c3d-efa0-4c2a-be4e-78c1b30a30d0}",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/teams/test_team/projects/myprj"
},
"html": {
"href": "https://bitbucket.org/account/user/test_team/projects/myprj"
},
"repositories": {
"href": "https://api.bitbucket.org/2.0/repositories/test_team?q='project.key=\"myprj\"'"
},
"avatar": {
"href": "https://bitbucket.org/account/user/test_team/projects/myprj/avatar/32"
}
},
"description": null,
"created_on": "2016-03-19T03:34:27.792230+00:00",
"key": "myprj",
"owner": {
"username": "test_team",
"display_name": "test team",
"type": "team",
"uuid": "{e0f17982-efab-43cb-8589-7bacabb37cab}",
"links": {
"self": {
"href": "https://api.bitbucket.org/2.0/teams/test_team"
},
"html": {
"href": "https://bitbucket.org/test_team/"
},
"avatar": {
"href": "https://bitbucket.org/account/test_team/avatar/32/"
}
}
},
"updated_on": "2016-03-19T03:34:27.792256+00:00",
"type": "project",
"is_private": false,
"name": "myprj"
}
40 changes: 33 additions & 7 deletions spec/lib/tinybucket/api/projects_api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,53 @@
RSpec.describe Tinybucket::Api::ProjectsApi do
include ApiResponseMacros

let(:api) { Tinybucket::Api::ProjectsApi.new }
let(:owner) { 'test_team' }
let(:request_path) { nil }
before do
api.owner = owner
stub_apiresponse(:get, request_path) if request_path
let(:options) { {} }
let(:api) do
Tinybucket::Api::ProjectsApi.new.tap do |api|
api.owner = owner
end
end

it { expect(api).to be_a_kind_of(Tinybucket::Api::BaseApi) }

describe 'list' do
subject { api.list() }
let(:request_path) { '/teams/test_team/projects/' }
before { stub_apiresponse(:get, request_path) }
subject { api.list() }
it { expect(subject).to be_an_instance_of(Tinybucket::Model::Page) }
end

describe 'find' do
let(:project_key) { 'myprj' }
let(:request_path) { "/teams/test_team/projects/#{project_key}" }
before { stub_apiresponse(:get, request_path) }
subject { api.find(project_key) }
it { expect(subject).to be_an_instance_of(Tinybucket::Model::Project) }
end

describe 'post' do
let(:request_path) { '/teams/test_team/projects/' }
let(:options) { { key: 'myprj', name: 'My project' } }
before { stub_apiresponse(:post, request_path) }
subject { api.post(options) }
it { expect(subject).to be_an_instance_of(Tinybucket::Model::Project) }
end

describe 'put' do
let(:project_key) { 'myprj' }
let(:request_path) { "/teams/test_team/projects/#{project_key}" }
let(:options) { { name: 'New project name' } }
before { stub_apiresponse(:put, request_path) }
subject { api.put(project_key, options) }
it { expect(subject).to be_an_instance_of(Tinybucket::Model::Project) }
end
end

describe 'delete' do
let(:project_key) { 'myprj' }
let(:request_path) { "/teams/test_team/projects/#{project_key}" }
before { stub_apiresponse(:delete, request_path) }
subject { api.delete(project_key) }
it { expect(subject).to be_nil }
end
end
16 changes: 12 additions & 4 deletions spec/lib/tinybucket/model/project_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@
include ApiResponseMacros

let(:model_json) { load_json_fixture('teams/test_team/projects/myprj/get') }
let(:owner) { model_json["owner"]["username"] }
let(:project_key) { model_json["name"] }
let(:instance) { Tinybucket::Model::Project.new(model_json) }

it_behaves_like 'model has acceptable_attributes',
Tinybucket::Model::Project,
load_json_fixture('teams/test_team/projects/myprj/get')

describe '#update' do
subject { instance.update({}) }
it { expect { subject }.to raise_error(NotImplementedError) }
let(:request_path) { "/teams/#{owner}/projects/#{project_key}" }
before { stub_apiresponse(:put, request_path) }
subject { instance.update(name: 'New project name') }
it do
expect(subject).to be_an_instance_of(Tinybucket::Model::Project)
end
end

describe '#destroy' do
subject { instance.destroy() }
it { expect { subject }.to raise_error(NotImplementedError) }
let(:request_path) { "/teams/#{owner}/projects/#{project_key}" }
before { stub_apiresponse(:delete, request_path) }
subject { instance.destroy }
it { expect(subject).to be_nil }
end

describe '#repos' do
Expand Down
9 changes: 6 additions & 3 deletions spec/lib/tinybucket/resource/projects_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
end

describe '#create' do
let(:params) { {} }
subject { resource.create(params) }
it { expect { subject }.to raise_error(NotImplementedError) }
let(:options) { { key: 'myprj', name: 'My project' } }
let(:request_path) { "/teams/#{owner}/projects/" }
before { stub_apiresponse(:post, request_path) }

subject { resource.create(options) }
it { expect(subject).to be_an_instance_of(Tinybucket::Model::Project) }
end

describe 'Enumerable Methods' do
Expand Down