noko 0.0.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ module Noko
2
+ class Client
3
+ def get_users(params = nil)
4
+ get('/v2/users', params)
5
+ end
6
+
7
+ def get_user(id)
8
+ get("/v2/users/#{id}")
9
+ end
10
+
11
+ def get_user_entries(id, params = nil)
12
+ get("/v2/users/#{id}/entries", params)
13
+ end
14
+
15
+ def get_user_expenses(id, params = nil)
16
+ get("/v2/users/#{id}/expenses", params)
17
+ end
18
+
19
+ def create_user(attributes)
20
+ post('/v2/users', attributes)
21
+ end
22
+
23
+ def update_user(id, attributes)
24
+ put("/v2/users/#{id}", attributes)
25
+ end
26
+
27
+ def delete_user(id)
28
+ delete("/v2/users/#{id}")
29
+ end
30
+
31
+ def reactivate_user(id)
32
+ put("/v2/users/#{id}/activate")
33
+ end
34
+
35
+ def deactivate_user(id)
36
+ put("/v2/users/#{id}/deactivate")
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,5 @@
1
+ module Noko
2
+ class Error < StandardError; end
3
+
4
+ class AuthenticationError < Error; end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'noko/record'
2
+ require 'uri'
3
+
4
+ module Noko
5
+ module LinkHeader # :nodoc:
6
+ extend self
7
+
8
+ REGEXP = /<([^>]+)>; rel="(\w+)"/
9
+
10
+ def parse(string)
11
+ string.scan(REGEXP).each_with_object(Record.new) do |(uri, rel), record|
12
+ record[rel.to_sym] = URI.parse(uri).request_uri
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ require 'cgi'
2
+
3
+ module Noko
4
+ module Params # :nodoc:
5
+ extend self
6
+
7
+ def join(path, params = nil)
8
+ return path if params.nil? || params.empty?
9
+
10
+ path + '?' + encode(params)
11
+ end
12
+
13
+ def encode(params)
14
+ params.map { |k, v| "#{escape(k)}=#{array_escape(v)}" }.join('&')
15
+ end
16
+
17
+ private
18
+
19
+ def array_escape(object)
20
+ Array(object).map { |value| escape(value) }.join(',')
21
+ end
22
+
23
+ def escape(component)
24
+ CGI.escape(component.to_s)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module Noko
2
+ class Record
3
+ def initialize(attributes = {})
4
+ @attributes = attributes
5
+ end
6
+
7
+ def [](name)
8
+ @attributes[name]
9
+ end
10
+
11
+ def []=(name, value)
12
+ @attributes[name] = value
13
+ end
14
+
15
+ def method_missing(name, *args, &block)
16
+ if @attributes.has_key?(name) && args.empty? && block.nil?
17
+ return @attributes[name]
18
+ else
19
+ super name, *args, &block
20
+ end
21
+ end
22
+
23
+ def respond_to_missing?(name, include_private = false)
24
+ @attributes.has_key?(name)
25
+ end
26
+
27
+ def to_h
28
+ @attributes
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Noko
2
+ VERSION = '1.4.0'
3
+ end
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'noko'
3
+ s.version = '1.4.0'
4
+ s.license = 'MIT'
5
+ s.platform = Gem::Platform::RUBY
6
+ s.authors = ['Tim Craft']
7
+ s.email = ['mail@timcraft.com']
8
+ s.homepage = 'https://github.com/timcraft/noko'
9
+ s.description = 'Ruby client for Version 2 of the Noko/Freckle API'
10
+ s.summary = 'Ruby client for Version 2 of the Noko/Freckle API'
11
+ s.files = Dir.glob('{lib,test}/**/*') + %w(LICENSE.txt README.md noko.gemspec)
12
+ s.required_ruby_version = '>= 1.9.3'
13
+ s.add_development_dependency('rake', '~> 12')
14
+ s.add_development_dependency('webmock', '~> 3.0')
15
+ s.add_development_dependency('minitest', '~> 5.0')
16
+ s.require_path = 'lib'
17
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientAccountTest < ClientTest
4
+ def test_get_account
5
+ expect_request(:get, "#{base_url}/account").with(auth_header).to_return(json_response)
6
+
7
+ assert_instance_of Noko::Record, client.get_account
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientCurrentUserTest < ClientTest
4
+ def test_get_current_user
5
+ expect_request(:get, "#{base_url}/current_user").with(auth_header).to_return(json_response)
6
+
7
+ assert_instance_of Noko::Record, client.get_current_user
8
+ end
9
+
10
+ def test_get_current_user_entries
11
+ expect_request(:get, "#{base_url}/current_user/entries").with(auth_header).to_return(json_array_response)
12
+
13
+ assert_equal [], client.get_current_user_entries
14
+ end
15
+
16
+ def test_get_current_user_entries_encodes_params
17
+ expect_request(:get, "#{base_url}/current_user/entries?billable=true")
18
+
19
+ client.get_current_user_entries(billable: true)
20
+ end
21
+
22
+ def test_get_current_user_expenses
23
+ expect_request(:get, "#{base_url}/current_user/expenses").with(auth_header).to_return(json_array_response)
24
+
25
+ assert_equal [], client.get_current_user_expenses
26
+ end
27
+
28
+ def test_get_current_user_expenses_encodes_params
29
+ expect_request(:get, "#{base_url}/current_user/expenses?invoiced=true")
30
+
31
+ client.get_current_user_expenses(invoiced: true)
32
+ end
33
+
34
+ def test_update_current_user
35
+ expect_request(:put, "#{base_url}/current_user").with(json_request).to_return(json_response)
36
+
37
+ assert_instance_of Noko::Record, client.update_current_user(week_start: 'monday')
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientEntriesTest < ClientTest
4
+ def test_get_entries
5
+ expect_request(:get, "#{base_url}/entries").with(auth_header).to_return(json_array_response)
6
+
7
+ assert_equal [], client.get_entries
8
+ end
9
+
10
+ def test_get_entries_encodes_params
11
+ expect_request(:get, "#{base_url}/entries?billable=true")
12
+
13
+ client.get_entries(billable: true)
14
+ end
15
+
16
+ def test_get_entries_encodes_project_ids
17
+ expect_request(:get, "#{base_url}/entries?project_ids=123,456,789")
18
+
19
+ client.get_entries(project_ids: ids)
20
+ end
21
+
22
+ def test_get_entry
23
+ expect_request(:get, "#{base_url}/entries/#{id}").with(auth_header).to_return(json_response)
24
+
25
+ assert_instance_of Noko::Record, client.get_entry(id)
26
+ end
27
+
28
+ def test_create_entry
29
+ expect_request(:post, "#{base_url}/entries").with(json_request).to_return(json_response.merge(status: 201))
30
+
31
+ assert_instance_of Noko::Record, client.create_entry(date: Date.today, minutes: 60)
32
+ end
33
+
34
+ def test_update_entry
35
+ expect_request(:put, "#{base_url}/entries/#{id}").with(json_request).to_return(json_response)
36
+
37
+ assert_instance_of Noko::Record, client.update_entry(id, minutes: 120)
38
+ end
39
+
40
+ def test_delete_entry
41
+ expect_request(:delete, "#{base_url}/entries/#{id}").with(auth_header).to_return(status: 204)
42
+
43
+ assert_equal :no_content, client.delete_entry(id)
44
+ end
45
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientErrorsTest < ClientTest
4
+ def test_bad_request_errors
5
+ message = 'The Project cannot be deleted because it has entries, expenses, or invoices.'
6
+
7
+ response = json_response.merge(status: 400, body: %({"message":"#{message}"}))
8
+
9
+ stub_request(:delete, "#{base_url}/projects/#{id}").to_return(response)
10
+
11
+ exception = assert_raises(Noko::Error) do
12
+ client.delete_project(id)
13
+ end
14
+
15
+ assert_includes exception.message, message
16
+ end
17
+
18
+ def test_authentication_errors
19
+ response = json_response.merge(status: 401)
20
+
21
+ stub_request(:get, "#{base_url}/entries").to_return(response)
22
+
23
+ assert_raises(Noko::AuthenticationError) do
24
+ client.get_entries
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,45 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientExpensesTest < ClientTest
4
+ def test_get_expenses
5
+ expect_request(:get, "#{base_url}/expenses").with(auth_header).to_return(json_array_response)
6
+
7
+ assert_equal [], client.get_expenses
8
+ end
9
+
10
+ def test_get_expenses_encodes_params
11
+ expect_request(:get, "#{base_url}/expenses?invoiced=true")
12
+
13
+ client.get_expenses(invoiced: true)
14
+ end
15
+
16
+ def test_get_expenses_encodes_ids
17
+ expect_request(:get, "#{base_url}/expenses?project_ids=123,456,789")
18
+
19
+ client.get_expenses(project_ids: ids)
20
+ end
21
+
22
+ def test_get_expense
23
+ expect_request(:get, "#{base_url}/expenses/#{id}").with(auth_header).to_return(json_response)
24
+
25
+ assert_instance_of Noko::Record, client.get_expense(id)
26
+ end
27
+
28
+ def test_create_expense
29
+ expect_request(:post, "#{base_url}/expenses").with(json_request).to_return(json_response.merge(status: 201))
30
+
31
+ assert_instance_of Noko::Record, client.create_expense(date: Date.today, project_id: id, price: '14.55')
32
+ end
33
+
34
+ def test_update_expense
35
+ expect_request(:put, "#{base_url}/expenses/#{id}").with(json_request).to_return(json_response)
36
+
37
+ assert_instance_of Noko::Record, client.update_expense(id, price: '19.99')
38
+ end
39
+
40
+ def test_delete_expense
41
+ expect_request(:delete, "#{base_url}/expenses/#{id}").with(auth_header).to_return(status: 204)
42
+
43
+ assert_equal :no_content, client.delete_expense(id)
44
+ end
45
+ end
@@ -0,0 +1,75 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientInvoicesTest < ClientTest
4
+ def test_get_invoices
5
+ expect_request(:get, "#{base_url}/invoices").with(auth_header).to_return(json_array_response)
6
+
7
+ assert_equal [], client.get_invoices
8
+ end
9
+
10
+ def test_get_invoices_encodes_params
11
+ expect_request(:get, "#{base_url}/invoices?state=unpaid")
12
+
13
+ client.get_invoices(state: :unpaid)
14
+ end
15
+
16
+ def test_get_invoice
17
+ expect_request(:get, "#{base_url}/invoices/#{id}").with(auth_header).to_return(json_response)
18
+
19
+ assert_instance_of Noko::Record, client.get_invoice(id)
20
+ end
21
+
22
+ def test_create_invoice
23
+ expect_request(:post, "#{base_url}/invoices").with(json_request).to_return(json_response.merge(status: 201))
24
+
25
+ assert_instance_of Noko::Record, client.create_invoice(invoice_date: Date.today)
26
+ end
27
+
28
+ def test_update_invoice
29
+ expect_request(:put, "#{base_url}/invoices/#{id}").with(json_request).to_return(json_response)
30
+
31
+ assert_instance_of Noko::Record, client.update_invoice(id, reference: 'AB 0001')
32
+ end
33
+
34
+ def test_mark_invoice_paid
35
+ expect_request(:put, "#{base_url}/invoices/#{id}/paid").with(auth_header).to_return(status: 204)
36
+
37
+ assert_equal :no_content, client.mark_invoice_paid(id)
38
+ end
39
+
40
+ def test_mark_invoice_unpaid
41
+ expect_request(:put, "#{base_url}/invoices/#{id}/unpaid").with(auth_header).to_return(status: 204)
42
+
43
+ assert_equal :no_content, client.mark_invoice_unpaid(id)
44
+ end
45
+
46
+ def test_get_invoice_entries
47
+ expect_request(:get, "#{base_url}/invoices/#{id}/entries").with(auth_header).to_return(json_array_response)
48
+
49
+ assert_equal [], client.get_invoice_entries(id)
50
+ end
51
+
52
+ def test_get_invoice_entries_encodes_params
53
+ expect_request(:get, "#{base_url}/invoices/#{id}/entries?billable=true")
54
+
55
+ client.get_invoice_entries(id, billable: true)
56
+ end
57
+
58
+ def test_get_invoice_expenses
59
+ expect_request(:get, "#{base_url}/invoices/#{id}/expenses").with(auth_header).to_return(json_array_response)
60
+
61
+ assert_equal [], client.get_invoice_expenses(id)
62
+ end
63
+
64
+ def test_get_invoice_expenses_encodes_params
65
+ expect_request(:get, "#{base_url}/invoices/#{id}/expenses?invoiced=false")
66
+
67
+ client.get_invoice_expenses(id, invoiced: false)
68
+ end
69
+
70
+ def test_delete_invoice
71
+ expect_request(:delete, "#{base_url}/invoices/#{id}").with(auth_header).to_return(status: 204)
72
+
73
+ assert_equal :no_content, client.delete_invoice(id)
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientOptionsTest < ClientTest
4
+ def user_agent
5
+ 'account.nokotime.com'
6
+ end
7
+
8
+ def access_token
9
+ 'oauth2-access-token'
10
+ end
11
+
12
+ def test_user_agent_option
13
+ client = Noko::Client.new(token: token, user_agent: user_agent)
14
+
15
+ expect_request(:get, "#{base_url}/entries").with(headers: {'User-Agent' => user_agent})
16
+
17
+ client.get_entries
18
+ end
19
+
20
+ def test_access_token_option
21
+ client = Noko::Client.new(access_token: access_token)
22
+
23
+ expect_request(:get, "#{base_url}/entries").with(headers: {'Authorization' => 'token oauth2-access-token'})
24
+
25
+ client.get_entries
26
+ end
27
+ end
@@ -0,0 +1,63 @@
1
+ require_relative '../client_test'
2
+
3
+ class ClientProjectGroupsTest < ClientTest
4
+ def test_get_project_groups
5
+ expect_request(:get, "#{base_url}/project_groups").with(auth_header).to_return(json_array_response)
6
+
7
+ assert_equal [], client.get_project_groups
8
+ end
9
+
10
+ def test_get_project_groups_encodes_params
11
+ expect_request(:get, "#{base_url}/project_groups?name=Sprockets")
12
+
13
+ client.get_project_groups(name: 'Sprockets')
14
+ end
15
+
16
+ def test_get_project_group
17
+ expect_request(:get, "#{base_url}/project_groups/#{id}").with(auth_header).to_return(json_response)
18
+
19
+ assert_instance_of Noko::Record, client.get_project_group(id)
20
+ end
21
+
22
+ def test_create_project_group
23
+ expect_request(:post, "#{base_url}/project_groups").with(json_request).to_return(json_response.merge(status: 201))
24
+
25
+ assert_instance_of Noko::Record, client.create_project_group(name: 'Sprockets, Inc.')
26
+ end
27
+
28
+ def test_get_project_group_entries
29
+ expect_request(:get, "#{base_url}/project_groups/#{id}/entries").with(auth_header).to_return(json_array_response)
30
+
31
+ assert_equal [], client.get_project_group_entries(id)
32
+ end
33
+
34
+ def test_get_project_group_entries_encodes_params
35
+ expect_request(:get, "#{base_url}/project_groups/#{id}/entries?billable=true")
36
+
37
+ client.get_project_group_entries(id, billable: true)
38
+ end
39
+
40
+ def test_get_project_group_projects
41
+ expect_request(:get, "#{base_url}/project_groups/#{id}/projects").with(auth_header).to_return(json_array_response)
42
+
43
+ assert_equal [], client.get_project_group_projects(id)
44
+ end
45
+
46
+ def test_get_project_group_projects_encodes_params
47
+ expect_request(:get, "#{base_url}/project_groups/#{id}/projects?billable=true")
48
+
49
+ client.get_project_group_projects(id, billable: true)
50
+ end
51
+
52
+ def test_update_project_group
53
+ expect_request(:put, "#{base_url}/project_groups/#{id}").with(json_request).to_return(json_response)
54
+
55
+ assert_instance_of Noko::Record, client.update_project_group(id, name: 'Sprockets, Inc.')
56
+ end
57
+
58
+ def test_delete_project_group
59
+ expect_request(:delete, "#{base_url}/project_groups/#{id}").with(auth_header).to_return(status: 204)
60
+
61
+ assert_equal :no_content, client.delete_project_group(id)
62
+ end
63
+ end