my_john_deere_api 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/lib/my_john_deere_api/helpers/case_conversion.rb +2 -4
  4. data/lib/my_john_deere_api/helpers/uri_helpers.rb +19 -0
  5. data/lib/my_john_deere_api/helpers.rb +1 -1
  6. data/lib/my_john_deere_api/model/asset.rb +43 -0
  7. data/lib/my_john_deere_api/model/asset_location.rb +27 -0
  8. data/lib/my_john_deere_api/model/field.rb +2 -4
  9. data/lib/my_john_deere_api/model/flag.rb +1 -1
  10. data/lib/my_john_deere_api/model/organization.rb +11 -1
  11. data/lib/my_john_deere_api/model.rb +2 -0
  12. data/lib/my_john_deere_api/request/collection/asset_locations.rb +19 -0
  13. data/lib/my_john_deere_api/request/collection/assets.rb +19 -0
  14. data/lib/my_john_deere_api/request/collection/base.rb +1 -1
  15. data/lib/my_john_deere_api/request/collection.rb +3 -1
  16. data/lib/my_john_deere_api/version.rb +1 -1
  17. data/test/lib/my_john_deere_api/{test_authorize.rb → authorize_test.rb} +0 -0
  18. data/test/lib/my_john_deere_api/{test_client.rb → client_test.rb} +0 -0
  19. data/test/lib/my_john_deere_api/{test_consumer.rb → consumer_test.rb} +0 -0
  20. data/test/lib/my_john_deere_api/errors/{test_access_token_error.rb → access_token_error_test.rb} +0 -0
  21. data/test/lib/my_john_deere_api/{test_errors.rb → errors_test.rb} +0 -0
  22. data/test/lib/my_john_deere_api/helpers/{test_case_conversion.rb → case_conversion_test.rb} +12 -2
  23. data/test/lib/my_john_deere_api/helpers/uri_helpers_test.rb +58 -0
  24. data/test/lib/my_john_deere_api/{test_helpers.rb → helpers_test.rb} +2 -2
  25. data/test/lib/my_john_deere_api/model/asset_location_test.rb +57 -0
  26. data/test/lib/my_john_deere_api/model/asset_test.rb +79 -0
  27. data/test/lib/my_john_deere_api/model/{test_field.rb → field_test.rb} +7 -0
  28. data/test/lib/my_john_deere_api/model/{test_flag.rb → flag_test.rb} +0 -0
  29. data/test/lib/my_john_deere_api/model/{test_organization.rb → organization_test.rb} +21 -0
  30. data/test/lib/my_john_deere_api/{test_model.rb → model_test.rb} +8 -0
  31. data/test/lib/my_john_deere_api/request/collection/asset_locations_test.rb +85 -0
  32. data/test/lib/my_john_deere_api/request/collection/assets_test.rb +83 -0
  33. data/test/lib/my_john_deere_api/request/collection/{test_base.rb → base_test.rb} +0 -0
  34. data/test/lib/my_john_deere_api/request/collection/{test_fields.rb → fields_test.rb} +0 -0
  35. data/test/lib/my_john_deere_api/request/collection/{test_flags.rb → flags_test.rb} +0 -0
  36. data/test/lib/my_john_deere_api/request/collection/{test_organizations.rb → organizations_test.rb} +0 -0
  37. data/test/lib/my_john_deere_api/request/{test_collection.rb → collection_test.rb} +8 -0
  38. data/test/lib/my_john_deere_api/{test_request.rb → request_test.rb} +0 -0
  39. data/test/lib/my_john_deere_api/{test_version.rb → version_test.rb} +0 -0
  40. data/test/{test_my_john_deere_api.rb → my_john_deere_api_test.rb} +0 -0
  41. data/test/support/vcr/get_asset_locations.yml +55 -0
  42. data/test/support/vcr/get_assets.yml +48 -0
  43. metadata +32 -22
  44. data/lib/my_john_deere_api/helpers/uri_path.rb +0 -9
  45. data/test/lib/my_john_deere_api/helpers/test_uri_path.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 308f6c3b51f2e879f9df9bb1b616947867acd261363aa72e98458f5e6234aa37
4
- data.tar.gz: '09257f1b9559a3a5b631f724bf4767151d49b0c6a9ddbc6ded2b024c3063bb8b'
3
+ metadata.gz: 8f27839609fe2e86e82d918edae99dd77d78cb9d7dad78c061d8ab198837953d
4
+ data.tar.gz: b302429624cc3f1a504e77235c105f94af9363bc075809f46f1659bf1b59859c
5
5
  SHA512:
6
- metadata.gz: 6a9f7d5b8303090de1101531ae6b9be02534c1c8d71179117ee5714238ae1ce4d067987a4a324e3a59316a95d7a613ab532c85989c4451109dc6236946be4195
7
- data.tar.gz: 369e58fbca78c338cf6e79935037cb154ba1fd5a44385e2623d62ef8a213bb9f60a3c74035efbad066b6a6b414a06e95828702844460890d757b4b6c51fa97d7
6
+ metadata.gz: 3b2509a126cf7aef80dc4984865660eb20285a4ccbb5aaec61a622449eebc3eb0628d1a44f3de78bfc95af42f639bbecd5a5796219b3d8be3ea4be7612e90b96
7
+ data.tar.gz: 2b401cacbc5c4fc8e9b224c89639689ceb681d8b697dfdd1b1f3ff62b1b91c5ea40508a2de61ade9ad8744773a90358067e9240faaa3f4088803c3caac1eb196
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rake/testtask'
2
2
 
3
3
  Rake::TestTask.new do |t|
4
4
  t.libs << 'test'
5
- t.pattern = 'test/**/test*.rb'
5
+ t.pattern = 'test/**/*_test.rb'
6
6
  end
7
7
 
8
8
  desc "Run tests"
@@ -1,6 +1,8 @@
1
1
  require 'uri'
2
2
 
3
3
  module MyJohnDeereApi::Helpers::CaseConversion
4
+ private
5
+
4
6
  ##
5
7
  # convert a text or camelcase string to underscore
6
8
 
@@ -8,8 +10,6 @@ module MyJohnDeereApi::Helpers::CaseConversion
8
10
  string.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/\s+/, '_').gsub(/_+/, '_').downcase
9
11
  end
10
12
 
11
- private :underscore
12
-
13
13
  ##
14
14
  # convert text or underscored string to camelcase
15
15
 
@@ -22,6 +22,4 @@ module MyJohnDeereApi::Helpers::CaseConversion
22
22
 
23
23
  new_list.join('')
24
24
  end
25
-
26
- private :camelize
27
25
  end
@@ -0,0 +1,19 @@
1
+ require 'uri'
2
+
3
+ module MyJohnDeereApi::Helpers::UriHelpers
4
+ private
5
+
6
+ ##
7
+ # extract just the path from the uri, excluding the platform prefix
8
+ def uri_path(uri)
9
+ URI.parse(uri).path.gsub(/^\/platform/, '')
10
+ end
11
+
12
+ ##
13
+ # infer id from uri
14
+
15
+ def id_from_uri(uri, label)
16
+ parts = uri.split('/')
17
+ parts[parts.index(label.to_s) + 1]
18
+ end
19
+ end
@@ -1,4 +1,4 @@
1
1
  module MyJohnDeereApi::Helpers
2
- autoload :UriPath, 'my_john_deere_api/helpers/uri_path'
2
+ autoload :UriHelpers, 'my_john_deere_api/helpers/uri_helpers'
3
3
  autoload :CaseConversion, 'my_john_deere_api/helpers/case_conversion'
4
4
  end
@@ -0,0 +1,43 @@
1
+ module MyJohnDeereApi
2
+ class Model::Asset
3
+ include Helpers::UriHelpers
4
+
5
+ attr_reader :accessor, :id, :title, :asset_category, :asset_type, :asset_sub_type, :last_modified_date, :links
6
+
7
+ ##
8
+ # arguments:
9
+ #
10
+ # [record] a JSON object of type 'Field', returned from the API.
11
+ #
12
+ # [accessor (optional)] a valid oAuth Access Token. This is only
13
+ # needed if further API requests are going
14
+ # to be made, as is the case with *flags*.
15
+
16
+ def initialize(record, accessor = nil)
17
+ @accessor = accessor
18
+
19
+ @id = record['id']
20
+ @title = record['title']
21
+ @asset_category = record['assetCategory']
22
+ @asset_type = record['assetType']
23
+ @asset_sub_type = record['assetSubType']
24
+ @last_modified_date = record['lastModifiedDate']
25
+
26
+ @links = {}
27
+
28
+ record['links'].each do |association|
29
+ @links[association['rel']] = uri_path(association['uri'])
30
+ end
31
+ end
32
+
33
+ ##
34
+ # locations associated with this asset
35
+
36
+ def locations
37
+ raise AccessTokenError unless accessor
38
+
39
+ return @locations if defined?(@locations)
40
+ @locations = MyJohnDeereApi::Request::Collection::AssetLocations.new(accessor, asset: id).all
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,27 @@
1
+ require 'json'
2
+
3
+ module MyJohnDeereApi
4
+ class Model::AssetLocation
5
+ include Helpers::UriHelpers
6
+
7
+ attr_reader :accessor, :timestamp, :geometry, :measurement_data, :links
8
+
9
+ ##
10
+ # arguments:
11
+ #
12
+ # [record] a JSON object of type 'Field', returned from the API.
13
+ #
14
+ # [accessor (optional)] a valid oAuth Access Token. This is only
15
+ # needed if further API requests are going
16
+ # to be made, as is the case with *flags*.
17
+
18
+ def initialize(record, accessor = nil)
19
+ @accessor = accessor
20
+
21
+ @timestamp = record['timestamp']
22
+ @geometry = JSON.parse(record['geometry'])
23
+ @measurement_data = record['measurementData']
24
+ @links = {}
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,6 @@
1
1
  module MyJohnDeereApi
2
2
  class Model::Field
3
- include Helpers::UriPath
3
+ include Helpers::UriHelpers
4
4
 
5
5
  attr_reader :name, :id, :links, :accessor
6
6
 
@@ -52,9 +52,7 @@ module MyJohnDeereApi
52
52
 
53
53
  def organization_id
54
54
  return @organization_id if defined?(@organization_id)
55
-
56
- parts = links['self'].split('/')
57
- @organization_id = parts[parts.index('organizations') + 1]
55
+ @organization_id = id_from_uri(links['self'], :organizations)
58
56
  end
59
57
  end
60
58
  end
@@ -3,7 +3,7 @@ require 'json'
3
3
  module MyJohnDeereApi
4
4
  class Model::Flag
5
5
  include Helpers::CaseConversion
6
- include Helpers::UriPath
6
+ include Helpers::UriHelpers
7
7
 
8
8
  attr_reader :id, :notes, :geometry, :links, :accessor
9
9
 
@@ -2,7 +2,7 @@ require 'uri'
2
2
 
3
3
  module MyJohnDeereApi
4
4
  class Model::Organization
5
- include Helpers::UriPath
5
+ include Helpers::UriHelpers
6
6
 
7
7
  attr_reader :name, :type, :id, :links, :accessor
8
8
 
@@ -47,5 +47,15 @@ module MyJohnDeereApi
47
47
  return @fields if defined?(@fields)
48
48
  @fields = MyJohnDeereApi::Request::Collection::Fields.new(accessor, organization: id).all
49
49
  end
50
+
51
+ ##
52
+ # assets associated with this organization
53
+
54
+ def assets
55
+ raise AccessTokenError unless accessor
56
+
57
+ return @assets if defined?(@assets)
58
+ @assets = MyJohnDeereApi::Request::Collection::Assets.new(accessor, organization: id).all
59
+ end
50
60
  end
51
61
  end
@@ -1,4 +1,6 @@
1
1
  module MyJohnDeereApi::Model
2
+ autoload :Asset, 'my_john_deere_api/model/asset'
3
+ autoload :AssetLocation, 'my_john_deere_api/model/asset_location'
2
4
  autoload :Organization, 'my_john_deere_api/model/organization'
3
5
  autoload :Field, 'my_john_deere_api/model/field'
4
6
  autoload :Flag, 'my_john_deere_api/model/flag'
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ module MyJohnDeereApi::Request
4
+ class Collection::AssetLocations < Collection::Base
5
+ ##
6
+ # The resource path for the first page in the collection
7
+
8
+ def resource
9
+ "/assets/#{associations[:asset]}/locations"
10
+ end
11
+
12
+ ##
13
+ # This is the class used to model the data
14
+
15
+ def model
16
+ MyJohnDeereApi::Model::AssetLocation
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ module MyJohnDeereApi::Request
4
+ class Collection::Assets < Collection::Base
5
+ ##
6
+ # The resource path for the first page in the collection
7
+
8
+ def resource
9
+ "/organizations/#{associations[:organization]}/assets"
10
+ end
11
+
12
+ ##
13
+ # This is the class used to model the data
14
+
15
+ def model
16
+ MyJohnDeereApi::Model::Asset
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
1
  module MyJohnDeereApi
2
2
  class Request::Collection::Base
3
3
  include Enumerable
4
- include Helpers::UriPath
4
+ include Helpers::UriHelpers
5
5
 
6
6
  attr_reader :accessor, :associations
7
7
 
@@ -1,6 +1,8 @@
1
1
  module MyJohnDeereApi::Request::Collection
2
2
  autoload :Base, 'my_john_deere_api/request/collection/base'
3
+ autoload :Assets, 'my_john_deere_api/request/collection/assets'
4
+ autoload :AssetLocations, 'my_john_deere_api/request/collection/asset_locations'
3
5
  autoload :Organizations, 'my_john_deere_api/request/collection/organizations'
4
6
  autoload :Fields, 'my_john_deere_api/request/collection/fields'
5
- autoload :Flags, 'my_john_deere_api/request/collection/flags'
7
+ autoload :Flags, 'my_john_deere_api/request/collection/flags'
6
8
  end
@@ -1,3 +1,3 @@
1
1
  module MyJohnDeereApi
2
- VERSION='0.4.1'
2
+ VERSION='0.5.0'
3
3
  end
@@ -2,6 +2,10 @@ require 'support/helper'
2
2
 
3
3
  class CaseConversionHelperSample
4
4
  include JD::Helpers::CaseConversion
5
+
6
+ def test
7
+ 'test'
8
+ end
5
9
  end
6
10
 
7
11
  describe 'Helpers::CaseConversion' do
@@ -29,7 +33,8 @@ describe 'Helpers::CaseConversion' do
29
33
  end
30
34
 
31
35
  it 'is a private method' do
32
- assert_raises(NoMethodError) { object.underscore('test') }
36
+ exception = assert_raises(NoMethodError) { object.underscore('test') }
37
+ assert_includes exception.message, 'private method'
33
38
  end
34
39
  end
35
40
 
@@ -50,7 +55,12 @@ describe 'Helpers::CaseConversion' do
50
55
  end
51
56
 
52
57
  it 'is a private method' do
53
- assert_raises(NoMethodError) { object.camelize('test') }
58
+ exception = assert_raises(NoMethodError) { object.camelize('test') }
59
+ assert_includes exception.message, 'private method'
54
60
  end
55
61
  end
62
+
63
+ it "preserves the public nature of the including class's other methods" do
64
+ assert_equal 'test', object.test
65
+ end
56
66
  end
@@ -0,0 +1,58 @@
1
+ require 'support/helper'
2
+
3
+ class UriHelpersHelperSample
4
+ include JD::Helpers::UriHelpers
5
+
6
+ def test
7
+ 'test'
8
+ end
9
+ end
10
+
11
+ describe 'UriHelpers' do
12
+ let(:object) { UriHelpersHelperSample.new }
13
+
14
+ describe '#uri_path' do
15
+ it 'extracts the path from the uri' do
16
+ path = object.send(:uri_path, 'https://example.com/turtles')
17
+ assert_equal '/turtles', path
18
+ end
19
+
20
+ it 'removes leading /platform from the path' do
21
+ path = object.send(:uri_path, 'https://example.com/platform/turtles')
22
+ assert_equal '/turtles', path
23
+ end
24
+
25
+ it 'preserves /platform in any other part of the path' do
26
+ path = object.send(:uri_path, 'https://example.com/platform/turtles/platform')
27
+ assert_equal '/turtles/platform', path
28
+ end
29
+
30
+ it 'is a private method' do
31
+ exception = assert_raises(NoMethodError) { object.uri_path('https://example.com/turtles')}
32
+ assert_includes exception.message, 'private method'
33
+ end
34
+ end
35
+
36
+ describe '#id_from_uri(uri, label)' do
37
+ it 'extracts the id immediately following a given label' do
38
+ uri = 'https://example.com/cows/123/pigs/456/turtles/789/birds/012'
39
+ assert_equal '789', object.send(:id_from_uri, uri, 'turtles')
40
+ end
41
+
42
+ it 'accepts a symbol for the label' do
43
+ uri = 'https://example.com/cows/123/pigs/456/turtles/789/birds/012'
44
+ assert_equal '789', object.send(:id_from_uri, uri, :turtles)
45
+ end
46
+
47
+ it 'is a private method' do
48
+ uri = 'https://example.com/cows/123/pigs/456/turtles/789/birds/012'
49
+
50
+ exception = assert_raises(NoMethodError) { object.id_from_uri(uri, 'turtles') }
51
+ assert_includes exception.message, 'private method'
52
+ end
53
+ end
54
+
55
+ it "preserves the public nature of the including class's other methods" do
56
+ assert_equal 'test', object.test
57
+ end
58
+ end
@@ -2,8 +2,8 @@ require 'support/helper'
2
2
 
3
3
  describe 'MyJohnDeereApi::Helpers' do
4
4
  describe 'loading dependencies' do
5
- it 'loads Helpers::UriPath' do
6
- assert JD::Helpers::UriPath
5
+ it 'loads Helpers::UriHelpers' do
6
+ assert JD::Helpers::UriHelpers
7
7
  end
8
8
 
9
9
  it 'loads Helpers::CaseConversion' do
@@ -0,0 +1,57 @@
1
+ require 'support/helper'
2
+ require 'json'
3
+
4
+ describe 'MyJohnDeereApi::Model::AssetLocation' do
5
+ let(:record) do
6
+ {
7
+ "@type"=>"ContributedAssetLocation",
8
+ "timestamp"=>"2017-09-20T21:30:59.000Z",
9
+ "geometry"=>"{\"type\": \"Feature\",\"geometry\": {\"geometries\": [{\"coordinates\": [ -103.115633, 41.670166],\"type\": \"Point\"}],\"type\": \"GeometryCollection\"}}",
10
+ "measurementData"=>[
11
+ {
12
+ "@type"=>"BasicMeasurement",
13
+ "name"=>"[1 Foot](https://app.realmfive.com/map?device=0x0080CDEF)",
14
+ "value"=>"82",
15
+ "unit"=>"cB"
16
+ }, {
17
+ "@type"=>"BasicMeasurement",
18
+ "name"=>"[2 Feet](https://app.realmfive.com/map?device=0x0080CDEF)",
19
+ "value"=>"31",
20
+ "unit"=>"cB"
21
+ }
22
+ ],
23
+ "links"=>[]
24
+ }
25
+ end
26
+
27
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
28
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
29
+
30
+ describe '#initialize' do
31
+ def link_for label
32
+ record['links'].detect{|link| link['rel'] == label}['uri'].gsub('https://sandboxapi.deere.com/platform', '')
33
+ end
34
+
35
+ it 'sets the attributes from the given record' do
36
+ location = JD::Model::AssetLocation.new(record)
37
+
38
+ assert_nil location.accessor
39
+
40
+ # basic attributes
41
+ assert_equal record['timestamp'], location.timestamp
42
+ assert_equal JSON.parse(record['geometry']), location.geometry
43
+ assert_equal record['measurementData'], location.measurement_data
44
+
45
+ # links to other things
46
+ assert_kind_of Hash, location.links
47
+ assert_equal 0, location.links.size
48
+ end
49
+
50
+ it 'accepts an optional accessor' do
51
+ accessor = 'mock-accessor'
52
+
53
+ location = JD::Model::AssetLocation.new(record, accessor)
54
+ assert_equal accessor, location.accessor
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,79 @@
1
+ require 'support/helper'
2
+
3
+ describe 'MyJohnDeereApi::Model::Asset' do
4
+ let(:record) do
5
+ {
6
+ "@type"=>"ContributedAsset",
7
+ "title"=>"Happy Device",
8
+ "assetCategory"=>"DEVICE",
9
+ "assetType"=>"SENSOR",
10
+ "assetSubType"=>"OTHER",
11
+ "id"=>"123456",
12
+ "lastModifiedDate"=>"2018-01-31T20:36:16.727Z",
13
+ "links"=>[
14
+ {"@type"=>"Link", "rel"=>"self", "uri"=>"https://sandboxapi.deere.com/platform/assets/123456"},
15
+ {"@type"=>"Link", "rel"=>"organization", "uri"=>"https://sandboxapi.deere.com/platform/organizations/234567"},
16
+ {"@type"=>"Link", "rel"=>"locations", "uri"=>"https://sandboxapi.deere.com/platform/assets/123456/locations"},
17
+ ]
18
+ }
19
+ end
20
+
21
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
22
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
23
+
24
+ describe '#initialize' do
25
+ def link_for label
26
+ record['links'].detect{|link| link['rel'] == label}['uri'].gsub('https://sandboxapi.deere.com/platform', '')
27
+ end
28
+
29
+ it 'sets the attributes from the given record' do
30
+ asset = JD::Model::Asset.new(record)
31
+
32
+ assert_nil asset.accessor
33
+
34
+ # basic attributes
35
+ assert_equal record['id'], asset.id
36
+ assert_equal record['title'], asset.title
37
+ assert_equal record['assetCategory'], asset.asset_category
38
+ assert_equal record['assetType'], asset.asset_type
39
+ assert_equal record['assetSubType'], asset.asset_sub_type
40
+ assert_equal record['lastModifiedDate'], asset.last_modified_date
41
+
42
+ # links to other things
43
+ assert_kind_of Hash, asset.links
44
+
45
+ ['self', 'organization', 'locations'].each do |association|
46
+ assert_equal link_for(association), asset.links[association]
47
+ end
48
+ end
49
+
50
+ it 'accepts an optional accessor' do
51
+ accessor = 'mock-accessor'
52
+
53
+ asset = JD::Model::Asset.new(record, accessor)
54
+ assert_equal accessor, asset.accessor
55
+ end
56
+ end
57
+
58
+ describe '#locations' do
59
+ it 'returns a collection of locations for this asset' do
60
+ accessor
61
+ organization = VCR.use_cassette('get_organizations') { client.organizations.first }
62
+ asset = VCR.use_cassette('get_assets') { organization.assets.first }
63
+ locations = VCR.use_cassette('get_asset_locations') { asset.locations }
64
+
65
+ assert_kind_of Array, locations
66
+
67
+ locations.each do |location|
68
+ assert_kind_of JD::Model::AssetLocation, location
69
+ end
70
+ end
71
+
72
+ it 'raises an exception if an accessor is not available' do
73
+ asset = JD::Model::Asset.new(record)
74
+
75
+ exception = assert_raises(JD::AccessTokenError) { asset.locations }
76
+ assert_includes exception.message, 'Access Token must be supplied'
77
+ end
78
+ end
79
+ end
@@ -71,4 +71,11 @@ describe 'MyJohnDeereApi::Model::Field' do
71
71
  assert_includes exception.message, 'Access Token must be supplied'
72
72
  end
73
73
  end
74
+
75
+ describe 'private #organization_id' do
76
+ it "infers the organization_id from links" do
77
+ field = JD::Model::Field.new(record)
78
+ assert_equal '123456', field.send(:organization_id)
79
+ end
80
+ end
74
81
  end
@@ -83,4 +83,25 @@ describe 'MyJohnDeereApi::Model::Organization' do
83
83
  assert_includes exception.message, 'Access Token must be supplied'
84
84
  end
85
85
  end
86
+
87
+ describe '#assets' do
88
+ it 'returns a collection of assets for this organization' do
89
+ accessor
90
+ organization = VCR.use_cassette('get_organizations') { client.organizations.first }
91
+ assets = VCR.use_cassette('get_assets') { organization.assets }
92
+
93
+ assert_kind_of Array, assets
94
+
95
+ assets.each do |assets|
96
+ assert_kind_of JD::Model::Asset, assets
97
+ end
98
+ end
99
+
100
+ it 'raises an exception if an accessor is not available' do
101
+ organization = JD::Model::Organization.new(record)
102
+
103
+ exception = assert_raises(JD::AccessTokenError) { organization.assets }
104
+ assert_includes exception.message, 'Access Token must be supplied'
105
+ end
106
+ end
86
107
  end
@@ -2,6 +2,14 @@ require 'support/helper'
2
2
 
3
3
  describe 'MyJohnDeereApi::Model' do
4
4
  describe 'loading dependencies' do
5
+ it 'loads Model::Asset' do
6
+ assert JD::Model::Asset
7
+ end
8
+
9
+ it 'loads Model::AssetLocation' do
10
+ assert JD::Model::AssetLocation
11
+ end
12
+
5
13
  it 'loads Model::Organization' do
6
14
  assert JD::Model::Organization
7
15
  end
@@ -0,0 +1,85 @@
1
+ require 'support/helper'
2
+ require 'yaml'
3
+ require 'json'
4
+
5
+ describe 'MyJohnDeereApi::Request::Collection::AssetLocations' do
6
+ let(:asset_id) do
7
+ contents = File.read('test/support/vcr/get_assets.yml')
8
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
9
+ JSON.parse(body)['values'].first['id']
10
+ end
11
+
12
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
13
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
14
+ let(:collection) { JD::Request::Collection::AssetLocations.new(accessor, asset: asset_id) }
15
+
16
+ describe '#initialize(access_token)' do
17
+ it 'accepts an access token' do
18
+ assert_kind_of OAuth::AccessToken, collection.accessor
19
+ end
20
+
21
+ it 'accepts associations' do
22
+ collection = JD::Request::Collection::AssetLocations.new(accessor, asset: '123')
23
+
24
+ assert_kind_of Hash, collection.associations
25
+ assert_equal '123', collection.associations[:asset]
26
+ end
27
+ end
28
+
29
+ describe '#resource' do
30
+ it 'returns /assets/{asset_id}/locations' do
31
+ assert_equal "/assets/#{asset_id}/locations", collection.resource
32
+ end
33
+ end
34
+
35
+ describe '#all' do
36
+ it 'returns all records' do
37
+ all = VCR.use_cassette('get_asset_locations', record: :new_episodes) { collection.all }
38
+
39
+ assert_kind_of Array, all
40
+ assert_equal collection.count, all.size
41
+ assert all.size > 0
42
+
43
+ all.each do |item|
44
+ assert_kind_of JD::Model::AssetLocation, item
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#count' do
50
+ let(:server_response) do
51
+ contents = File.read('test/support/vcr/get_asset_locations.yml')
52
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
53
+ JSON.parse(body)
54
+ end
55
+
56
+ let(:server_count) { server_response['total'] }
57
+
58
+ it 'returns the total count of records in the collection' do
59
+ count = VCR.use_cassette('get_asset_locations') { collection.count }
60
+
61
+ assert_equal server_count, count
62
+ end
63
+ end
64
+
65
+ describe 'results' do
66
+ let(:location_timestamps) do
67
+ contents = File.read('test/support/vcr/get_asset_locations.yml')
68
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
69
+ JSON.parse(body)['values'].map{|v| v['timestamp']}
70
+ end
71
+
72
+ it 'returns all records as a single enumerator' do
73
+ count = VCR.use_cassette('get_asset_locations') { collection.count }
74
+ timestamps = VCR.use_cassette('get_asset_locations', record: :new_episodes) { collection.map(&:timestamp) }
75
+
76
+ assert_kind_of Array, timestamps
77
+ assert_equal count, timestamps.size
78
+ assert timestamps.size > 0
79
+
80
+ location_timestamps.each do |expected_timestamp|
81
+ assert_includes timestamps, expected_timestamp
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,83 @@
1
+ require 'support/helper'
2
+ require 'yaml'
3
+ require 'json'
4
+
5
+ describe 'MyJohnDeereApi::Request::Collection::Assets' do
6
+ let(:organization_id) do
7
+ contents = File.read('test/support/vcr/get_organizations.yml')
8
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
9
+ JSON.parse(body)['values'].first['id']
10
+ end
11
+
12
+ let(:client) { JD::Client.new(API_KEY, API_SECRET, environment: :sandbox, access: [ACCESS_TOKEN, ACCESS_SECRET]) }
13
+ let(:accessor) { VCR.use_cassette('catalog') { client.send(:accessor) } }
14
+ let(:collection) { JD::Request::Collection::Assets.new(accessor, organization: organization_id) }
15
+
16
+ describe '#initialize(access_token)' do
17
+ it 'accepts an access token' do
18
+ assert_kind_of OAuth::AccessToken, collection.accessor
19
+ end
20
+
21
+ it 'accepts associations' do
22
+ collection = JD::Request::Collection::Assets.new(accessor, organization: '123')
23
+
24
+ assert_kind_of Hash, collection.associations
25
+ assert_equal '123', collection.associations[:organization]
26
+ end
27
+ end
28
+
29
+ describe '#resource' do
30
+ it 'returns /organizations/{org_id}/assets' do
31
+ assert_equal "/organizations/#{organization_id}/assets", collection.resource
32
+ end
33
+ end
34
+
35
+ describe '#all' do
36
+ it 'returns all records' do
37
+ all = VCR.use_cassette('get_assets', record: :new_episodes) { collection.all }
38
+
39
+ assert_kind_of Array, all
40
+ assert_equal collection.count, all.size
41
+
42
+ all.each do |item|
43
+ assert_kind_of JD::Model::Asset, item
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '#count' do
49
+ let(:server_response) do
50
+ contents = File.read('test/support/vcr/get_assets.yml')
51
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
52
+ JSON.parse(body)
53
+ end
54
+
55
+ let(:server_count) { server_response['total'] }
56
+
57
+ it 'returns the total count of records in the collection' do
58
+ count = VCR.use_cassette('get_assets') { collection.count }
59
+
60
+ assert_equal server_count, count
61
+ end
62
+ end
63
+
64
+ describe 'results' do
65
+ let(:asset_titles) do
66
+ contents = File.read('test/support/vcr/get_assets.yml')
67
+ body = YAML.load(contents)['http_interactions'].first['response']['body']['string']
68
+ JSON.parse(body)['values'].map{|v| v['title']}
69
+ end
70
+
71
+ it 'returns all records as a single enumerator' do
72
+ count = VCR.use_cassette('get_assets') { collection.count }
73
+ titles = VCR.use_cassette('get_assets', record: :new_episodes) { collection.map(&:title) }
74
+
75
+ assert_kind_of Array, titles
76
+ assert_equal count, titles.size
77
+
78
+ asset_titles.each do |expected_title|
79
+ assert_includes titles, expected_title
80
+ end
81
+ end
82
+ end
83
+ end
@@ -6,6 +6,14 @@ describe 'MyJohnDeereApi::Request::Collection' do
6
6
  assert JD::Request::Collection::Base
7
7
  end
8
8
 
9
+ it 'loads Request::Collection::Assets' do
10
+ assert JD::Request::Collection::Assets
11
+ end
12
+
13
+ it 'loads Request::Collection::AssetLocations' do
14
+ assert JD::Request::Collection::AssetLocations
15
+ end
16
+
9
17
  it 'loads Request::Collection::Organizations' do
10
18
  assert JD::Request::Collection::Organizations
11
19
  end
@@ -0,0 +1,55 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://sandboxapi.deere.com/platform/assets/029c288a-14d9-459f-8ee6-b4e840e672a1/locations
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.deere.axiom.v3+json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ User-Agent:
15
+ - OAuth gem v0.5.4
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="johndeere-wgmADngYCRmfpEbVgSyc709wnyRux5J7PAv8SE7B",
18
+ oauth_nonce="qTv5xV20gMbjd7IiRtg8xZlNfZHXX7Dmo1JrfP6xY1A", oauth_signature="exY2Q9m%2FlxXM%2BryRe6b9P7FmT1c%3D",
19
+ oauth_signature_method="HMAC-SHA1", oauth_timestamp="1578698931", oauth_token="47bbb9c9-41a8-4bec-8127-e3c5760af2f6",
20
+ oauth_version="1.0"
21
+ response:
22
+ status:
23
+ code: 200
24
+ message: OK
25
+ headers:
26
+ Date:
27
+ - Fri, 10 Jan 2020 23:28:51 GMT
28
+ Content-Type:
29
+ - application/vnd.deere.axiom.v3+json;charset=UTF-8
30
+ X-Deere-Handling-Server:
31
+ - ip-10-214-44-15
32
+ X-Frame-Options:
33
+ - SAMEORIGIN
34
+ X-Deere-Elapsed-Ms:
35
+ - '58'
36
+ Cache-Control:
37
+ - no-store
38
+ Content-Language:
39
+ - en-US
40
+ Transfer-Encoding:
41
+ - chunked
42
+ body:
43
+ encoding: ASCII-8BIT
44
+ string: '{"links":[{"rel":"self","uri":"https://sandboxapi.deere.com/platform/assets/029c288a-14d9-459f-8ee6-b4e840e672a1/locations"}],"total":2,"values":[{"@type":"ContributedAssetLocation","timestamp":"2017-09-20T21:30:59.000Z","geometry":"{\"type\":
45
+ \"Feature\",\"geometry\": {\"geometries\": [{\"coordinates\": [ -103.115633,
46
+ 41.670166],\"type\": \"Point\"}],\"type\": \"GeometryCollection\"}}","measurementData":[{"@type":"BasicMeasurement","name":"[1
47
+ Foot](https://app.realmfive.com/map?device=0x0080CDEF)","value":"82","unit":"cB"},{"@type":"BasicMeasurement","name":"[2
48
+ Feet](https://app.realmfive.com/map?device=0x0080CDEF)","value":"31","unit":"cB"}],"links":[]},{"@type":"ContributedAssetLocation","timestamp":"2017-09-20T21:29:59.000Z","geometry":"{\"type\":
49
+ \"Feature\",\"geometry\": {\"geometries\": [{\"coordinates\": [ -103.115633,
50
+ 41.670166],\"type\": \"Point\"}],\"type\": \"GeometryCollection\"}}","measurementData":[{"@type":"BasicMeasurement","name":"[Moisture
51
+ - 1 Foot](https://app.realmfive.com/map?device=0x0080CDEF)","value":"82","unit":"cB"},{"@type":"BasicMeasurement","name":"[Moisture
52
+ - 2 Feet](https://app.realmfive.com/map?device=0x0080CDEF)","value":"31","unit":"cB"}],"links":[]}]}'
53
+ http_version:
54
+ recorded_at: Fri, 10 Jan 2020 23:28:52 GMT
55
+ recorded_with: VCR 5.0.0
@@ -0,0 +1,48 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://sandboxapi.deere.com/platform/organizations/444563/assets
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - application/vnd.deere.axiom.v3+json
12
+ Accept-Encoding:
13
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
14
+ User-Agent:
15
+ - OAuth gem v0.5.4
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="johndeere-wgmADngYCRmfpEbVgSyc709wnyRux5J7PAv8SE7B",
18
+ oauth_nonce="6Q43mOlqL5POK9tW4g378nTYY2NzAPxtWCpE6ngfM", oauth_signature="ECsBHW1vv01ybBLwrHTne421c%2Bw%3D",
19
+ oauth_signature_method="HMAC-SHA1", oauth_timestamp="1578694864", oauth_token="47bbb9c9-41a8-4bec-8127-e3c5760af2f6",
20
+ oauth_version="1.0"
21
+ response:
22
+ status:
23
+ code: 200
24
+ message: OK
25
+ headers:
26
+ Date:
27
+ - Fri, 10 Jan 2020 22:21:04 GMT
28
+ Content-Type:
29
+ - application/vnd.deere.axiom.v3+json;charset=UTF-8
30
+ X-Deere-Handling-Server:
31
+ - ip-10-214-44-225
32
+ X-Frame-Options:
33
+ - SAMEORIGIN
34
+ X-Deere-Elapsed-Ms:
35
+ - '32'
36
+ Cache-Control:
37
+ - no-store
38
+ Content-Language:
39
+ - en-US
40
+ Transfer-Encoding:
41
+ - chunked
42
+ body:
43
+ encoding: ASCII-8BIT
44
+ string: '{"links":[{"rel":"self","uri":"https://sandboxapi.deere.com/platform/organizations/444563/assets"}],"total":3,"values":[{"@type":"ContributedAsset","title":"Flex
45
+ (Watermark)","assetCategory":"DEVICE","assetType":"SENSOR","assetSubType":"ENVIRONMENTAL","lastModifiedDate":"2019-09-20T21:13:38.232Z","id":"029c288a-14d9-459f-8ee6-b4e840e672a1","links":[{"@type":"Link","rel":"self","uri":"https://sandboxapi.deere.com/platform/assets/029c288a-14d9-459f-8ee6-b4e840e672a1"},{"@type":"Link","rel":"contributionDefinition","uri":"https://sandboxapi.deere.com/platform/contributionDefinitions/d93611c7-6f74-474f-9569-2cf88f866a32"},{"@type":"Link","rel":"organization","uri":"https://sandboxapi.deere.com/platform/organizations/444563"},{"@type":"Link","rel":"locations","uri":"https://sandboxapi.deere.com/platform/assets/029c288a-14d9-459f-8ee6-b4e840e672a1/locations"},{"@type":"Link","rel":"lastKnownLocation","uri":"https://sandboxapi.deere.com/platform/assets/029c288a-14d9-459f-8ee6-b4e840e672a1/locations?lastKnown=true"}]},{"@type":"ContributedAsset","title":"Pivot","assetCategory":"DEVICE","assetType":"SENSOR","assetSubType":"IRRIGATION_PIVOT","lastModifiedDate":"2019-09-20T21:14:13.931Z","id":"900b3657-0868-46b7-8322-70f204d44281","links":[{"@type":"Link","rel":"self","uri":"https://sandboxapi.deere.com/platform/assets/900b3657-0868-46b7-8322-70f204d44281"},{"@type":"Link","rel":"contributionDefinition","uri":"https://sandboxapi.deere.com/platform/contributionDefinitions/d93611c7-6f74-474f-9569-2cf88f866a32"},{"@type":"Link","rel":"organization","uri":"https://sandboxapi.deere.com/platform/organizations/444563"},{"@type":"Link","rel":"locations","uri":"https://sandboxapi.deere.com/platform/assets/900b3657-0868-46b7-8322-70f204d44281/locations"},{"@type":"Link","rel":"lastKnownLocation","uri":"https://sandboxapi.deere.com/platform/assets/900b3657-0868-46b7-8322-70f204d44281/locations?lastKnown=true"}]},{"@type":"ContributedAsset","title":"Float","assetCategory":"DEVICE","assetType":"SENSOR","assetSubType":"ENVIRONMENTAL","lastModifiedDate":"2019-09-20T21:13:58.799Z","id":"da668043-a366-4dac-bfc9-3aeafe1175dd","links":[{"@type":"Link","rel":"self","uri":"https://sandboxapi.deere.com/platform/assets/da668043-a366-4dac-bfc9-3aeafe1175dd"},{"@type":"Link","rel":"contributionDefinition","uri":"https://sandboxapi.deere.com/platform/contributionDefinitions/d93611c7-6f74-474f-9569-2cf88f866a32"},{"@type":"Link","rel":"organization","uri":"https://sandboxapi.deere.com/platform/organizations/444563"},{"@type":"Link","rel":"locations","uri":"https://sandboxapi.deere.com/platform/assets/da668043-a366-4dac-bfc9-3aeafe1175dd/locations"},{"@type":"Link","rel":"lastKnownLocation","uri":"https://sandboxapi.deere.com/platform/assets/da668043-a366-4dac-bfc9-3aeafe1175dd/locations?lastKnown=true"}]}]}'
46
+ http_version:
47
+ recorded_at: Fri, 10 Jan 2020 22:21:05 GMT
48
+ recorded_with: VCR 5.0.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: my_john_deere_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaime. Bellmyer
@@ -103,46 +103,56 @@ files:
103
103
  - lib/my_john_deere_api/errors/access_token_error.rb
104
104
  - lib/my_john_deere_api/helpers.rb
105
105
  - lib/my_john_deere_api/helpers/case_conversion.rb
106
- - lib/my_john_deere_api/helpers/uri_path.rb
106
+ - lib/my_john_deere_api/helpers/uri_helpers.rb
107
107
  - lib/my_john_deere_api/model.rb
108
+ - lib/my_john_deere_api/model/asset.rb
109
+ - lib/my_john_deere_api/model/asset_location.rb
108
110
  - lib/my_john_deere_api/model/field.rb
109
111
  - lib/my_john_deere_api/model/flag.rb
110
112
  - lib/my_john_deere_api/model/organization.rb
111
113
  - lib/my_john_deere_api/request.rb
112
114
  - lib/my_john_deere_api/request/collection.rb
115
+ - lib/my_john_deere_api/request/collection/asset_locations.rb
116
+ - lib/my_john_deere_api/request/collection/assets.rb
113
117
  - lib/my_john_deere_api/request/collection/base.rb
114
118
  - lib/my_john_deere_api/request/collection/fields.rb
115
119
  - lib/my_john_deere_api/request/collection/flags.rb
116
120
  - lib/my_john_deere_api/request/collection/organizations.rb
117
121
  - lib/my_john_deere_api/version.rb
118
- - test/lib/my_john_deere_api/errors/test_access_token_error.rb
119
- - test/lib/my_john_deere_api/helpers/test_case_conversion.rb
120
- - test/lib/my_john_deere_api/helpers/test_uri_path.rb
121
- - test/lib/my_john_deere_api/model/test_field.rb
122
- - test/lib/my_john_deere_api/model/test_flag.rb
123
- - test/lib/my_john_deere_api/model/test_organization.rb
124
- - test/lib/my_john_deere_api/request/collection/test_base.rb
125
- - test/lib/my_john_deere_api/request/collection/test_fields.rb
126
- - test/lib/my_john_deere_api/request/collection/test_flags.rb
127
- - test/lib/my_john_deere_api/request/collection/test_organizations.rb
128
- - test/lib/my_john_deere_api/request/test_collection.rb
129
- - test/lib/my_john_deere_api/test_authorize.rb
130
- - test/lib/my_john_deere_api/test_client.rb
131
- - test/lib/my_john_deere_api/test_consumer.rb
132
- - test/lib/my_john_deere_api/test_errors.rb
133
- - test/lib/my_john_deere_api/test_helpers.rb
134
- - test/lib/my_john_deere_api/test_model.rb
135
- - test/lib/my_john_deere_api/test_request.rb
136
- - test/lib/my_john_deere_api/test_version.rb
122
+ - test/lib/my_john_deere_api/authorize_test.rb
123
+ - test/lib/my_john_deere_api/client_test.rb
124
+ - test/lib/my_john_deere_api/consumer_test.rb
125
+ - test/lib/my_john_deere_api/errors/access_token_error_test.rb
126
+ - test/lib/my_john_deere_api/errors_test.rb
127
+ - test/lib/my_john_deere_api/helpers/case_conversion_test.rb
128
+ - test/lib/my_john_deere_api/helpers/uri_helpers_test.rb
129
+ - test/lib/my_john_deere_api/helpers_test.rb
130
+ - test/lib/my_john_deere_api/model/asset_location_test.rb
131
+ - test/lib/my_john_deere_api/model/asset_test.rb
132
+ - test/lib/my_john_deere_api/model/field_test.rb
133
+ - test/lib/my_john_deere_api/model/flag_test.rb
134
+ - test/lib/my_john_deere_api/model/organization_test.rb
135
+ - test/lib/my_john_deere_api/model_test.rb
136
+ - test/lib/my_john_deere_api/request/collection/asset_locations_test.rb
137
+ - test/lib/my_john_deere_api/request/collection/assets_test.rb
138
+ - test/lib/my_john_deere_api/request/collection/base_test.rb
139
+ - test/lib/my_john_deere_api/request/collection/fields_test.rb
140
+ - test/lib/my_john_deere_api/request/collection/flags_test.rb
141
+ - test/lib/my_john_deere_api/request/collection/organizations_test.rb
142
+ - test/lib/my_john_deere_api/request/collection_test.rb
143
+ - test/lib/my_john_deere_api/request_test.rb
144
+ - test/lib/my_john_deere_api/version_test.rb
145
+ - test/my_john_deere_api_test.rb
137
146
  - test/support/helper.rb
138
147
  - test/support/vcr/app_consumer.yml
139
148
  - test/support/vcr/catalog.yml
140
149
  - test/support/vcr/get_access_token.yml
150
+ - test/support/vcr/get_asset_locations.yml
151
+ - test/support/vcr/get_assets.yml
141
152
  - test/support/vcr/get_fields.yml
142
153
  - test/support/vcr/get_flags.yml
143
154
  - test/support/vcr/get_organizations.yml
144
155
  - test/support/vcr/get_request_token.yml
145
- - test/test_my_john_deere_api.rb
146
156
  homepage: https://github.com/Intellifarm/my_john_deere_api
147
157
  licenses:
148
158
  - MIT
@@ -1,9 +0,0 @@
1
- require 'uri'
2
-
3
- module MyJohnDeereApi::Helpers::UriPath
4
- def uri_path(uri)
5
- URI.parse(uri).path.gsub(/^\/platform/, '')
6
- end
7
-
8
- private :uri_path
9
- end
@@ -1,28 +0,0 @@
1
- require 'support/helper'
2
-
3
- class UriPathHelperSample
4
- include JD::Helpers::UriPath
5
- end
6
-
7
- describe 'UriPath' do
8
- let(:object) { UriPathHelperSample.new }
9
-
10
- it 'extracts the path from the uri' do
11
- path = object.send(:uri_path, 'https://example.com/turtles')
12
- assert_equal '/turtles', path
13
- end
14
-
15
- it 'removes leading /platform from the path' do
16
- path = object.send(:uri_path, 'https://example.com/platform/turtles')
17
- assert_equal '/turtles', path
18
- end
19
-
20
- it 'preserves /platform in any other part of the path' do
21
- path = object.send(:uri_path, 'https://example.com/platform/turtles/platform')
22
- assert_equal '/turtles/platform', path
23
- end
24
-
25
- it 'is a private method' do
26
- assert_raises(NoMethodError) { object.uri_path('https://example.com/turtles')}
27
- end
28
- end