teamworkpm 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c413f43deba985a73fdd5018cc17443937216457
4
+ data.tar.gz: d6e75bb5cd041eb286f4bdb0392a51653e4b3b2b
5
+ SHA512:
6
+ metadata.gz: acb7c0ce9217d67f59759268c2db3ae278bfa9ef6cf6fe4915e57acbddb498d607eb975816d33fd4128b8fbfa140e19926c8b529f124d10d71a327e946b8a68a
7
+ data.tar.gz: 3b35842ad4704ff3f221169db6785d879b27ca8105f9c7772cd96aec0410b59af8d907d561913de9d4a19ca56baacc6f3098cdf4e93f35ca4bec12610ede383a
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <http://unlicense.org>
@@ -0,0 +1,39 @@
1
+ # Teamwork Gem
2
+
3
+ Teamwork is project management software for teams. This gem attempts to get as close to 100% coverage for the API as possible,
4
+ with a few notable holes being uploading files and managing companies. I would welcome any pull-request that add these capabilities.
5
+
6
+ ## Usage
7
+
8
+ To get started add `gem "teamworkpm"` to your `Gemfile` (if using Bundler) or run `gem install teamworkpm`.
9
+
10
+ In order to use the `teamworkpm` gem you will need to have an active teamwork account with full API access. You can read the docs
11
+ on getting your API key [here](http://developer.teamwork.com/enabletheapiandgetyourkey).
12
+
13
+ ### Authentication
14
+
15
+ Authentication to the API is done through the class method `authenticate`. `Teamwork.authenticate(api_key)` will log you in. Failed authentication will return a `401`, else the account for the authenticated user.
16
+
17
+ ### Capabilites
18
+
19
+ #### Account
20
+
21
+ # GET the authenticated users's information
22
+ # Return Teamwork::Thing
23
+ Teamwork.account_info
24
+
25
+
26
+ # GET an authenticated user
27
+ # This part is unique to the rest of the lib
28
+ # in that it uses a different path for the API call.
29
+ # What we can get from this, however, is the subdomain that the
30
+ # user is a part of and store that for future API calls.
31
+ # http://authenticate.teamworkpm.net/authenticate.json
32
+ # Return Teamwork::Thing (or 401 if auth fails)
33
+ Teamwwork.authenticate(api_key)
34
+
35
+ #### Activity
36
+
37
+ # GET the recent activity stream across all projects
38
+ # Return [Teamwork::Thing]
39
+ Teamwork.recent_activity(options) # Defaults to returning 60 items
@@ -0,0 +1,8 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :test => :spec
8
+ task :default => :spec
@@ -0,0 +1,26 @@
1
+ require "teamwork/client"
2
+
3
+ module Teamwork
4
+
5
+ class << self
6
+
7
+ attr_accessor :api_key, :subdomain
8
+
9
+ def client
10
+ @client ||= Teamwork::Client.new
11
+ end
12
+
13
+ def respond_to?(method_name, include_private = false)
14
+ client.respond_to?(method_name, include_private) || super
15
+ end
16
+
17
+ private
18
+
19
+ def method_missing(method_name, *args, &block)
20
+ return super unless client.respond_to?(method_name)
21
+ client.send(method_name, *args, &block)
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,84 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'json'
4
+ Dir[File.dirname(__FILE__) + '/client/*.rb'].each {|file| require file }
5
+
6
+ module Teamwork
7
+
8
+ class Client
9
+
10
+ include Teamwork::Client::Account
11
+ include Teamwork::Client::Activity
12
+ include Teamwork::Client::Comment
13
+ include Teamwork::Client::Company
14
+ include Teamwork::Client::File
15
+ include Teamwork::Client::Message
16
+ include Teamwork::Client::Notebook
17
+ include Teamwork::Client::People
18
+ include Teamwork::Client::Project
19
+ include Teamwork::Client::Task
20
+ include Teamwork::Client::Timer
21
+
22
+ def api_endpoint
23
+ @api_endpoint ||= "http://#{Teamwork.subdomain}.teamworkpm.net/"
24
+ end
25
+
26
+ def self.authenticated?
27
+ !Teamwork.subdomain.nil? || !Teamwork.api_key.nil?
28
+ end
29
+
30
+ def resources
31
+ %w{links milestones files notebooks tasks}
32
+ end
33
+
34
+ private
35
+
36
+ def objects_from_response(method, path, key, params = nil, format = ".json")
37
+ res = response(method, path, key, params, format)[key]
38
+ return [] if res.nil?
39
+ res.map { |item| Teamwork::Thing.new(item) }
40
+ end
41
+
42
+ def object_from_response(method, path, key, params = nil, format = ".json")
43
+ Teamwork::Thing.new(response(method, path, key, params, format)[key])
44
+ end
45
+
46
+ def response(method, path, key, params, format)
47
+ send(method.to_sym, "#{path}#{format}", params).body
48
+ end
49
+
50
+ def get(path, params = nil)
51
+ request(:get, path, params)
52
+ end
53
+
54
+ def post(path, params = nil)
55
+ request(:post, path, params)
56
+ end
57
+
58
+ def put(path, params = nil)
59
+ request(:put, path, params)
60
+ end
61
+
62
+ def delete_path(path, params = nil)
63
+ request(:delete, path, params)
64
+ end
65
+
66
+ def request(method, path, parameters = {})
67
+ connection.send(method.to_sym, path, parameters).env
68
+ end
69
+
70
+ def connection(endpoint = api_endpoint)
71
+ Faraday.new endpoint do |c|
72
+ c.request :multipart
73
+ c.request :json
74
+ c.request :url_encoded
75
+ c.response :json, content_type: /\bjson$/
76
+ c.adapter :net_http
77
+ c.headers[:cache_control] = 'no-cache'
78
+ c.basic_auth(Teamwork.api_key, '')
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,34 @@
1
+ require 'uri'
2
+
3
+ module Teamwork
4
+ class Client
5
+
6
+ module Account
7
+
8
+ # GET the authenticated users's information
9
+ # Return Teamwork::Thing
10
+ def account_info
11
+ object_from_response(:get, "account", "account")
12
+ end
13
+
14
+ # GET an authenticated user
15
+ # This part is unique to the rest of the lib
16
+ # in that it uses a different path for the API call.
17
+ # What we can get from this, however, is the subdomain that the
18
+ # user is a part of and store that for future API calls.
19
+ # http://authenticate.teamworkpm.net/authenticate.json
20
+ # Return Teamwork::Thing (or 401 if auth fails)
21
+ def authenticate(api_key)
22
+ Teamwork.api_key = api_key
23
+ result = connection("http://authenticate.teamworkpm.net").send(:get, "authenticate.json").env
24
+ return result.status if result.status == 401
25
+
26
+ thing = Thing.new(result.body["account"])
27
+ Teamwork.subdomain = thing.code
28
+ thing
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Activity
5
+
6
+ # GET the recent activity stream across all projects
7
+ # Return [Teamwork::Thing]
8
+ def recent_activity(options = {})
9
+ objects_from_response(:get, "latestActivity", "activity", options.merge({maxItems: 60, onlyStarred: false}))
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,73 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Comment
5
+
6
+ # GET comments for a given resource
7
+ # params:
8
+ # resource: String (links, milestones, files, notebooks, tasks)
9
+ # id: UnsignedInt (the id of the resource that you want to get comments on)
10
+ # options:
11
+ # page: UnsignedInt
12
+ # pageSize: UnsignedInt (default 50)
13
+ # return: [Teamwork::Thing]
14
+ def get_comments(resource, id, options = {})
15
+ validate_resource(resource)
16
+ objects_from_response(:get, "#{resource}/#{id}/comments", "comments", options)
17
+ end
18
+
19
+ # GET a single comment by ID
20
+ # params:
21
+ # id: UnsignedInt
22
+ # return Teamwork::Thing
23
+ def get_comment(id)
24
+ object_from_response(:get, "comments/#{id}", "comment")
25
+ end
26
+
27
+ # POST a new comment
28
+ # params:
29
+ # resource: String (links, milestones, files, notebooks, tasks)
30
+ # id: UnsignedInt (the id of the resource that you want to post comments to)
31
+ # options:
32
+ # body: String
33
+ # notify: String (who should we notify of this comment?)
34
+ # ispprivate: Boolean (default false)
35
+ # pendingFileAttachments: String (see http://developer.teamwork.com/uploadingfiles for more info)
36
+ # return Teamwork::Thing
37
+ def post_comment(resource, id, options)
38
+ validate_resource(resource)
39
+ get_comment(send(:post, "#{resource}/#{id}/comments.json", comment: options).body["commentId"])
40
+ end
41
+
42
+ # PUT an update to a comment
43
+ # params:
44
+ # id: UnsignedInt (the id of the comment that you want update)
45
+ # options:
46
+ # body: String
47
+ # notify: String (who should we notify of this comment?)
48
+ # ispprivate: Boolean (default false)
49
+ # pendingFileAttachments: String (see http://developer.teamwork.com/uploadingfiles for more info)
50
+ # return Integer (status code)
51
+ def update_comment(id, options)
52
+ send(:put, "comments/#{id}.json", comment: options).status
53
+ end
54
+
55
+ # DELETE a comment
56
+ # params:
57
+ # id: UnsignedInt (the comment id to delete)
58
+ # return Int (status code)
59
+ def delete_comment(id)
60
+ send(:delete, "coments/#{id}")
61
+ end
62
+
63
+
64
+ private
65
+
66
+ def validate_resource(resource)
67
+ raise TypeError, "Valid resources are #{resources.join(", ")}" unless resources.include?(resource)
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,15 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Company
5
+
6
+ # GET a list of companies
7
+ # Return [Teamwork::Thing]
8
+ def get_companies
9
+ objects_from_response(:get, "companies", "companies")
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module File
5
+
6
+ # GET a single message
7
+ # return Teamwork::Thing
8
+ def get_file(id)
9
+ object_from_response(:get, "files/#{id}", "file")
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Message
5
+
6
+ # GET a single message
7
+ # return Teamwork::Thing
8
+ def get_message(id)
9
+ object_from_response(:get, "posts/#{id}", "post")
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Notebook
5
+
6
+ # GET all notebooks
7
+ # This method is a bit different as the response nests notebooks under
8
+ # projects, which itself is an array. Once the projects are parsed,
9
+ # lets map those and save the notebooks to an array
10
+ # options:
11
+ # includeContent: Boolean (default false)
12
+ # return: [Teamwork::Thing]
13
+ def get_notebooks(options = {})
14
+ objects_from_response(:get, "notebooks", "projects", options)
15
+ .map { |project| project.notebooks.map { |notebook| Teamwork::Thing.new(notebook) }}.flatten
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module People
5
+
6
+ # GET all people
7
+ # options:
8
+ # page: UnsignedInt
9
+ # pageSize: UnsignedInt (default 50)
10
+ # return: [Teamwork::Thing]
11
+ def get_people(options = {})
12
+ objects_from_response(:get, "people", "people", options)
13
+ end
14
+
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,111 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Project
5
+
6
+ # GET the recent activity stream for a given project
7
+ # Return [Teamwork::Thing]
8
+ def project_activity(project_id, options = {})
9
+ objects_from_response(:get, "projects/#{project_id}/latestActivity", "activity", options.merge({maxItems: 50}))
10
+ end
11
+
12
+ # GET time entries for the project
13
+ # options:
14
+ # page: UnsignedInt
15
+ # fromdate: YYYYMMDD
16
+ # fromtime: HH:MM
17
+ # todate: YYYYMMDD
18
+ # totime: HH:MM
19
+ # sortorder: (ASC, DESC) (defaults to ascending order by date (oldest to newest))
20
+ # Return [Teamwork::Thing]
21
+ def project_timers(project_id, options = {})
22
+ objects_from_response(:get, "projects/#{project_id}/time_entries", "time-entries", options)
23
+ end
24
+
25
+ # GET people on a project
26
+ # params:
27
+ # project_id: UnsignedInt
28
+ # Return [Teamwork::Thing]
29
+ def project_people(project_id)
30
+ objects_from_response(:get, "projects/#{project_id}/people", "people")
31
+ end
32
+
33
+ # GET files on a project
34
+ # Unfortunately the API returns a project with the associated files as a key
35
+ # in the hash. So lets get the files out after.
36
+ # params:
37
+ # project_id: UnsignedInt
38
+ # Return [Teamwork::Thing]
39
+ def project_files(project_id)
40
+ object_from_response(:get, "projects/#{project_id}/files", "project").files.map { |file| Teamwork::Thing.new(file) }
41
+ end
42
+
43
+ # GET messages on a project
44
+ # params:
45
+ # project_id: UnsignedInt
46
+ # Return [Teamwork::Thing]
47
+ def project_messages(project_id)
48
+ objects_from_response(:get, "projects/#{project_id}/posts", "posts")
49
+ end
50
+
51
+ # GET companies on a project
52
+ # params:
53
+ # project_id: UnsignedInt
54
+ # Return [Teamwork::Thing]
55
+ def project_companies(project_id)
56
+ objects_from_response(:get, "projects/#{project_id}/companies", "people")
57
+ end
58
+
59
+ # GET a list of projects
60
+ # Options:
61
+ # status: (ALL, ACTIVE, ARCHIVED)
62
+ # updatedAfterDate: YYYYMMDD
63
+ # updatedAfterTime: HH:MM
64
+ # createdAfterDate: YYYYMMDD
65
+ # createdAfterTime: HH:MM
66
+ # includePeople: boolean
67
+ # orderby: (name, companyName, lastActivityDate)
68
+ # starred: true
69
+ # page: UnsignedInt
70
+ # Return [Teamwork::Thing]
71
+ def projects(options = {})
72
+ url = options[:starred].nil? ? "projects" : "projects/starred"
73
+ objects_from_response(:get, url, "projects", options)
74
+ end
75
+
76
+ # GET a single project
77
+ # Return Teamwork::Thing
78
+ def project(id)
79
+ object_from_response(:get, "project/#{id}", "project")
80
+ end
81
+
82
+ # PUT a start to a project
83
+ # Return Boolean
84
+ def toggle_project_star(id, star: true)
85
+ url = star ? "projects/#{id}/star" : "projects/#{id}/unstar"
86
+ object_from_response(:put, url, "project", project: options)
87
+ end
88
+
89
+
90
+ # POST a new project
91
+ # Return Teamwork::Thing
92
+ def create_project(options = {})
93
+ object_from_response(:post, "projects", "project", project: options)
94
+ end
95
+
96
+ # PUT a current project
97
+ # Return Teamwork::Thing
98
+ def update_project(id, options = {})
99
+ object_from_response(:put, "projects/#{id}", "project", project: options)
100
+ end
101
+
102
+ # DELETE a current project
103
+ # Return Boolean
104
+ def delete_project(id)
105
+ send(:delete, "projects/#{id}")
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,48 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Task
5
+
6
+ # GET time entries for the project
7
+ # options:
8
+ # page: UnsignedInt
9
+ # fromdate: YYYYMMDD
10
+ # fromtime: HH:MM
11
+ # todate: YYYYMMDD
12
+ # totime: HH:MM
13
+ # sortorder: (ASC, DESC) (defaults to ascending order by date (oldest to newest))
14
+ # Return [Teamwork::Thing]
15
+ def task_timers(task_id, options)
16
+ objects_from_response(:get, "todo_items/#{task_id}/time_entries", "time-entries", options)
17
+ end
18
+
19
+ # GET all tasks across all projects
20
+ # options:
21
+ # filter: (all, anytime, overdue, today, tomorrow, thisweek, within7, within14, within30, within365, nodate, nostartdate, completed)
22
+ # page: UnsignedInt
23
+ # pageSize: 250 (the amount of tasks to return per page)
24
+ # startdate: YYYYMMDD
25
+ # endDate: YYYYMMDD
26
+ # updatedAfterDate: YYYYMMDD
27
+ # showDeleted: Boolean (default false)
28
+ # includeCompletedTasks: Boolean (default false)
29
+ # includeCompletedSubtasks: Boolean (default false)
30
+ # creator-ids: Comma-delimited list of user ids
31
+ # include: (nodate, nostartdate, noduedate, overdue)
32
+ # responsible-party-ids (-1 (all assigned), 0 (all unassigned), or specific user ids as a comma-delimited-list)
33
+ # sort (duedate, startdate, dateadded, priority, project, company)
34
+ # getSubTasks: Boolean (default true)
35
+ # nestSubTasks: Boolean (default false)
36
+ # getFiles: Boolean (default false)
37
+ # dataSet: String (default full) (options: full, newTaskDefaults)
38
+ # includeToday: Boolean (default true) (When using the filter option with any of the following options; within7,within14,within30,within365. You can choose to exclude deadlines for today by passing this parameter as false.)
39
+ # ignore-start-dates: Boolean (default false) (When using the filter option, you can choose to include start dates matching the filtering critera by passing this parameter as true. By default, only due dates are checked against the filter.)
40
+ # Return [Teamwork::Thing]
41
+ def all_tasks(options = {})
42
+ objects_from_response(:get, "tasks", "todo-items", options)
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ module Teamwork
2
+
3
+ class Thing
4
+
5
+ def initialize(item)
6
+ item.each_pair do |key, value|
7
+ key = key.split(/[\s-]/).join('_').downcase
8
+ singleton_class.class_eval do; attr_accessor key; end
9
+ send("#{key}=", value)
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,41 @@
1
+ module Teamwork
2
+ class Client
3
+
4
+ module Timer
5
+
6
+ # GET recent time entries
7
+ # options:
8
+ # page: UnsignedInt
9
+ # fromdate: YYYYMMDD
10
+ # fromtime: HH:MM
11
+ # todate: YYYYMMDD
12
+ # totime: HH:MM
13
+ # sortorder: (ASC, DESC) (defaults to ascending order by date (oldest to newest))
14
+ # Return [Teamwork::Thing]
15
+ def time_entries(options = {})
16
+ objects_from_response(:get, "time_entries", "time-entries", options)
17
+ end
18
+
19
+
20
+ # GET a single time entry
21
+ # Return Teamwork::Thing
22
+ def time_entry(id)
23
+ object_from_response(:get, "time_entries/#{id}", "time-entry")
24
+ end
25
+
26
+ # PUT a single time entry
27
+ # Return Teamwork::Thing
28
+ def update_time_entry(options = {})
29
+ object_from_response(:put, "time_entries/#{id}", "time-entry", "time-entry" => options)
30
+ end
31
+
32
+ # DELETE a single time entry
33
+ # Return boolean
34
+ def delete_time_entry(id)
35
+ send(:delete, "time_entries/#{id}")
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module Teamwork
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/teamwork'
2
+ require_relative 'support/helpers.rb'
3
+ require 'rspec'
4
+ require 'dotenv'
5
+
6
+ Dotenv.load
7
+
8
+ RSpec.configure do |config|
9
+
10
+ config.filter_run focus: true
11
+ config.run_all_when_everything_filtered = true
12
+ config.include Helpers
13
+
14
+ end
@@ -0,0 +1,7 @@
1
+ module Helpers
2
+
3
+ def authenticate
4
+ Teamwork.authenticate(ENV["API_KEY"])
5
+ end
6
+
7
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Account do
4
+
5
+ context "#authenticate" do
6
+
7
+ before(:each) do
8
+ Teamwork.api_key = ''
9
+ Teamwork.subdomain = ''
10
+ end
11
+
12
+ it "responds" do
13
+ expect(Teamwork.authenticate(ENV["API_KEY"])).to be_a(Teamwork::Thing)
14
+ end
15
+
16
+ it "sets subdomain" do
17
+ expect { Teamwork.authenticate(ENV["API_KEY"]) }.to change{Teamwork.subdomain}.to ENV["SUBDOMAIN"]
18
+ end
19
+
20
+ it "sets api key" do
21
+ expect { Teamwork.authenticate(ENV["API_KEY"]) }.to change{Teamwork.api_key}.to ENV["API_KEY"]
22
+ end
23
+
24
+ context "bad keys" do
25
+
26
+ it "raises error" do
27
+ expect(Teamwork.authenticate("this-should-blow-up")).to eq(401)
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ context "#account_info" do
35
+
36
+ before(:each) { authenticate }
37
+
38
+ it "is a thing" do
39
+ expect(Teamwork.account_info).to be_a(Teamwork::Thing)
40
+ end
41
+
42
+ it "fails if not authenticated" do
43
+ Teamwork.authenticate("no-good-key")
44
+ expect { Teamwork.account_info }.to raise_error
45
+ end
46
+
47
+ it "fills out the name" do
48
+ expect(Teamwork.account_info.name).to_not be_nil
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Comment do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ let(:comment_body) { {body: "Hey", notify: "", isprivate: false, pendingFileAttachments: ""} }
8
+ let(:comment_id) { ENV["COMMENT_ID"] }
9
+ let(:task) { ENV["TASK_ID"] }
10
+
11
+ context "#get_comments" do
12
+
13
+ it "responds" do
14
+ expect(Teamwork.respond_to?(:get_comments)).to eq(true)
15
+ end
16
+
17
+ it "raises exception on invalid option" do
18
+ expect { Teamwork.get_comments("sports", 14) }.to raise_error
19
+ end
20
+
21
+ it "builds array" do
22
+ expect(Teamwork.get_comments("tasks", Teamwork.all_tasks.first.id)).to be_a(Array)
23
+ end
24
+
25
+ end
26
+
27
+ context "#get_comment" do
28
+
29
+ let(:comments) { Teamwork.get_comments("tasks", task) }
30
+
31
+ it "responds" do
32
+ expect(Teamwork.respond_to?(:get_comment)).to eq(true)
33
+ end
34
+
35
+ it "is a thing" do
36
+ expect(Teamwork.get_comment(comments.first.id)).to be_a(Teamwork::Thing)
37
+ end
38
+
39
+ end
40
+
41
+ context "#post_comment" do
42
+
43
+ it "creates a comment" do
44
+ expect(Teamwork.respond_to?(:post_comment)).to eq(true)
45
+ end
46
+
47
+ it "returns 201 on success" do
48
+ expect(Teamwork.client.send(:post, "tasks/#{task}/comments.json", comment: comment_body).status).to eq(201)
49
+ end
50
+
51
+ it "returns the new comment" do
52
+ expect(Teamwork.post_comment("tasks", task, comment_body)).to be_a(Teamwork::Thing)
53
+ end
54
+
55
+ end
56
+
57
+ context "#update_comment" do
58
+
59
+ it "creates a comment" do
60
+ expect(Teamwork.respond_to?(:update_comment)).to eq(true)
61
+ end
62
+
63
+ it "returns 200 on success" do
64
+ expect(Teamwork.update_comment(comment_id, comment_body)).to eq(200)
65
+ end
66
+
67
+ end
68
+
69
+ context "#delete_comment" do
70
+
71
+ it "deletes a comment" do
72
+ expect(Teamwork.respond_to?(:delete_comment)).to eq(true)
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Company do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#get_companies" do
8
+
9
+ it "should respond" do
10
+ expect(Teamwork.respond_to?(:get_companies)).to eq(true)
11
+ end
12
+
13
+ it "should get people" do
14
+ expect(Teamwork.get_companies).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ context "#project_companies" do
20
+
21
+ it "should respond" do
22
+ expect(Teamwork.respond_to?(:project_companies)).to eq(true)
23
+ end
24
+
25
+ it "should get companies" do
26
+ expect(Teamwork.project_companies(Teamwork.projects.first.id)).to be_a(Array)
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::File do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#get_file" do
8
+
9
+ let(:file_id) { ENV["FILE_ID"] }
10
+
11
+ it "should respond" do
12
+ expect(Teamwork.respond_to?(:get_file)).to eq(true)
13
+ end
14
+
15
+ it "should get files" do
16
+ expect(Teamwork.get_file(file_id)).to be_a(Teamwork::Thing)
17
+ end
18
+
19
+ end
20
+
21
+ context "#project_files" do
22
+
23
+ let(:project_id) { ENV["PROJECT_ID"] }
24
+ let(:files) { Teamwork.project_files(project_id) }
25
+
26
+ it "retrieves files" do
27
+ expect(files).to be_a(Array)
28
+ end
29
+
30
+ it "isn't empty" do
31
+ expect(files).to_not be_empty
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Message do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#project_messages" do
8
+
9
+ it "should respond" do
10
+ expect(Teamwork.respond_to?(:project_messages)).to eq(true)
11
+ end
12
+
13
+ it "should get messages" do
14
+ expect(Teamwork.project_messages(Teamwork.projects.first.id)).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ context "#get_message" do
20
+
21
+ let(:message_id) { ENV["MESSAGE_ID"] }
22
+
23
+ it "should respond" do
24
+ expect(Teamwork.respond_to?(:get_message)).to eq(true)
25
+ end
26
+
27
+ it "should get messages" do
28
+ expect(Teamwork.get_message(message_id)).to be_a(Teamwork::Thing)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Notebook do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#get_notebooks" do
8
+
9
+ it "should respond" do
10
+ expect(Teamwork.respond_to?(:get_notebooks)).to eq(true)
11
+ end
12
+
13
+ it "should get notebooks" do
14
+ expect(Teamwork.get_notebooks).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::People do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#get_people" do
8
+
9
+ it "should respond" do
10
+ expect(Teamwork.respond_to?(:get_people)).to eq(true)
11
+ end
12
+
13
+ it "should get people" do
14
+ expect(Teamwork.get_people).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ context "#project_people" do
20
+
21
+ it "should respond" do
22
+ expect(Teamwork.respond_to?(:project_people)).to eq(true)
23
+ end
24
+
25
+ it "should get people" do
26
+ expect(Teamwork.project_people(Teamwork.projects.first.id)).to be_a(Array)
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Project do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#project_activity" do
8
+
9
+ let(:project_id) { ENV["PROJECT_ID"] }
10
+ let(:activity) { Teamwork.project_activity(project_id) }
11
+
12
+ it "retrieves activity" do
13
+ expect(activity).to be_a(Array)
14
+ end
15
+
16
+ it "isn't empty" do
17
+ expect(activity).to_not be_empty
18
+ end
19
+
20
+ end
21
+
22
+ context "#project_timers" do
23
+
24
+ # This one is interesting as if timers have not been enabled for
25
+ # the project the API returns a 404 rather than an empty array.
26
+ # The difficulty here is that listing all the projects doesn't show whether
27
+ # the project has enabled a timer or not. We will need to set something
28
+ # up with VCR here.
29
+ let(:project_id) { ENV["PROJECT_ID"] }
30
+ let(:timers) { Teamwork.project_timers(project_id) }
31
+
32
+ it "retrieves activity" do
33
+ expect(timers).to be_a(Array)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Task do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#all_tasks" do
8
+
9
+ it "should respond" do
10
+ expect(Teamwork.respond_to?(:all_tasks)).to eq(true)
11
+ end
12
+
13
+ it "should build an array" do
14
+ expect(Teamwork.all_tasks).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork::Client::Timer do
4
+
5
+ before(:each) { authenticate }
6
+
7
+ context "#time_entries" do
8
+
9
+ it "responds" do
10
+ expect(Teamwork.respond_to?(:time_entries)).to be true
11
+ end
12
+
13
+ it "Array" do
14
+ expect(Teamwork.time_entries).to be_a(Array)
15
+ end
16
+
17
+ end
18
+
19
+ context "#time_entry" do
20
+
21
+ it "fetches a single item" do
22
+ expect(Teamwork.time_entry(Teamwork.time_entries.first.id)).to be_a(Teamwork::Thing)
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Teamwork do
4
+
5
+ it "returns a Teamwork::Client" do
6
+ expect(Teamwork.client).to be_kind_of Teamwork::Client
7
+ end
8
+
9
+ it "forwards methods to its client" do
10
+ expect(Teamwork.respond_to?(:authenticate)).to be true
11
+ end
12
+
13
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'teamwork/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "teamworkpm"
8
+ spec.version = Teamwork::VERSION
9
+ spec.authors = [" Brandon Hansen"]
10
+ spec.email = ["bh@jesusculture.com"]
11
+ spec.description = "A Ruby wrapper to the Teamwork PM API"
12
+ spec.summary = "A Ruby wrapper to the Teamwork PM API"
13
+ spec.homepage = "http://teamwork.com/"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = %w(LICENSE README.md Rakefile teamworkpm.gemspec)
17
+ spec.files += Dir.glob("lib/**/*.rb")
18
+ spec.files += Dir.glob("spec/**/*")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency 'faraday', "~> 0.8"
24
+ spec.add_dependency 'faraday_middleware'
25
+ spec.add_dependency 'htmlentities', "~> 4.3"
26
+ spec.add_dependency 'multi_json', '~> 1.8'
27
+ spec.add_dependency 'multipart-post'
28
+
29
+ spec.add_development_dependency 'dotenv', '~> 0.9', '>= 0.9.0'
30
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: teamworkpm
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - " Brandon Hansen"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.8'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: htmlentities
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.3'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: multi_json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: multipart-post
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: dotenv
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.9'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.9.0
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '0.9'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 0.9.0
103
+ description: A Ruby wrapper to the Teamwork PM API
104
+ email:
105
+ - bh@jesusculture.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - LICENSE
111
+ - README.md
112
+ - Rakefile
113
+ - lib/teamwork.rb
114
+ - lib/teamwork/client.rb
115
+ - lib/teamwork/client/account.rb
116
+ - lib/teamwork/client/activity.rb
117
+ - lib/teamwork/client/comment.rb
118
+ - lib/teamwork/client/company.rb
119
+ - lib/teamwork/client/file.rb
120
+ - lib/teamwork/client/message.rb
121
+ - lib/teamwork/client/notebook.rb
122
+ - lib/teamwork/client/people.rb
123
+ - lib/teamwork/client/project.rb
124
+ - lib/teamwork/client/task.rb
125
+ - lib/teamwork/client/thing.rb
126
+ - lib/teamwork/client/timer.rb
127
+ - lib/teamwork/version.rb
128
+ - spec/spec_helper.rb
129
+ - spec/support/helpers.rb
130
+ - spec/teamwork/client/account_spec.rb
131
+ - spec/teamwork/client/comment_spec.rb
132
+ - spec/teamwork/client/company_spec.rb
133
+ - spec/teamwork/client/file_spec.rb
134
+ - spec/teamwork/client/message_spec.rb
135
+ - spec/teamwork/client/notebook_spec.rb
136
+ - spec/teamwork/client/people_spec.rb
137
+ - spec/teamwork/client/project_spec.rb
138
+ - spec/teamwork/client/task_spec.rb
139
+ - spec/teamwork/client/timer_spec.rb
140
+ - spec/teamwork_spec.rb
141
+ - teamworkpm.gemspec
142
+ homepage: http://teamwork.com/
143
+ licenses:
144
+ - MIT
145
+ metadata: {}
146
+ post_install_message:
147
+ rdoc_options: []
148
+ require_paths:
149
+ - lib
150
+ required_ruby_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ required_rubygems_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirements: []
161
+ rubyforge_project:
162
+ rubygems_version: 2.2.2
163
+ signing_key:
164
+ specification_version: 4
165
+ summary: A Ruby wrapper to the Teamwork PM API
166
+ test_files:
167
+ - spec/spec_helper.rb
168
+ - spec/support/helpers.rb
169
+ - spec/teamwork/client/account_spec.rb
170
+ - spec/teamwork/client/comment_spec.rb
171
+ - spec/teamwork/client/company_spec.rb
172
+ - spec/teamwork/client/file_spec.rb
173
+ - spec/teamwork/client/message_spec.rb
174
+ - spec/teamwork/client/notebook_spec.rb
175
+ - spec/teamwork/client/people_spec.rb
176
+ - spec/teamwork/client/project_spec.rb
177
+ - spec/teamwork/client/task_spec.rb
178
+ - spec/teamwork/client/timer_spec.rb
179
+ - spec/teamwork_spec.rb