noko 0.0.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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