intercom 3.9.4 → 4.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +340 -222
  3. data/Rakefile +1 -1
  4. data/changes.txt +25 -0
  5. data/lib/intercom.rb +33 -22
  6. data/lib/intercom/api_operations/archive.rb +2 -1
  7. data/lib/intercom/api_operations/delete.rb +16 -0
  8. data/lib/intercom/api_operations/find.rb +5 -2
  9. data/lib/intercom/api_operations/find_all.rb +4 -3
  10. data/lib/intercom/api_operations/list.rb +4 -1
  11. data/lib/intercom/api_operations/load.rb +4 -2
  12. data/lib/intercom/api_operations/nested_resource.rb +70 -0
  13. data/lib/intercom/api_operations/save.rb +6 -4
  14. data/lib/intercom/api_operations/scroll.rb +4 -5
  15. data/lib/intercom/api_operations/search.rb +3 -2
  16. data/lib/intercom/article.rb +7 -0
  17. data/lib/intercom/base_collection_proxy.rb +72 -0
  18. data/lib/intercom/client.rb +36 -25
  19. data/lib/intercom/client_collection_proxy.rb +17 -39
  20. data/lib/intercom/collection.rb +7 -0
  21. data/lib/intercom/company.rb +8 -0
  22. data/lib/intercom/contact.rb +21 -3
  23. data/lib/intercom/conversation.rb +5 -0
  24. data/lib/intercom/data_attribute.rb +7 -0
  25. data/lib/intercom/deprecated_leads_collection_proxy.rb +22 -0
  26. data/lib/intercom/deprecated_resources.rb +13 -0
  27. data/lib/intercom/errors.rb +3 -0
  28. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  29. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  30. data/lib/intercom/lead.rb +21 -0
  31. data/lib/intercom/lib/typed_json_deserializer.rb +42 -37
  32. data/lib/intercom/note.rb +4 -0
  33. data/lib/intercom/request.rb +37 -33
  34. data/lib/intercom/scroll_collection_proxy.rb +33 -38
  35. data/lib/intercom/search_collection_proxy.rb +30 -65
  36. data/lib/intercom/section.rb +23 -0
  37. data/lib/intercom/service/article.rb +20 -0
  38. data/lib/intercom/service/base_service.rb +7 -0
  39. data/lib/intercom/service/collection.rb +24 -0
  40. data/lib/intercom/service/company.rb +0 -12
  41. data/lib/intercom/service/contact.rb +21 -10
  42. data/lib/intercom/service/conversation.rb +12 -3
  43. data/lib/intercom/service/data_attribute.rb +20 -0
  44. data/lib/intercom/service/lead.rb +41 -0
  45. data/lib/intercom/service/note.rb +4 -8
  46. data/lib/intercom/service/section.rb +7 -0
  47. data/lib/intercom/service/subscription.rb +2 -2
  48. data/lib/intercom/service/tag.rb +9 -9
  49. data/lib/intercom/service/visitor.rb +17 -8
  50. data/lib/intercom/tag.rb +4 -0
  51. data/lib/intercom/traits/api_resource.rb +44 -18
  52. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  53. data/lib/intercom/user.rb +12 -3
  54. data/lib/intercom/utils.rb +13 -2
  55. data/lib/intercom/version.rb +1 -1
  56. data/lib/intercom/visitor.rb +0 -2
  57. data/spec/spec_helper.rb +843 -520
  58. data/spec/unit/intercom/admin_spec.rb +2 -2
  59. data/spec/unit/intercom/article_spec.rb +40 -0
  60. data/spec/unit/intercom/base_collection_proxy_spec.rb +30 -0
  61. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  62. data/spec/unit/intercom/client_spec.rb +28 -25
  63. data/spec/unit/intercom/collection_spec.rb +32 -0
  64. data/spec/unit/intercom/company_spec.rb +13 -15
  65. data/spec/unit/intercom/contact_spec.rb +344 -33
  66. data/spec/unit/intercom/conversation_spec.rb +55 -7
  67. data/spec/unit/intercom/count_spec.rb +4 -4
  68. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  69. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  70. data/spec/unit/intercom/event_spec.rb +9 -11
  71. data/spec/unit/intercom/job_spec.rb +24 -24
  72. data/spec/unit/intercom/lead_spec.rb +57 -0
  73. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  74. data/spec/unit/intercom/message_spec.rb +1 -1
  75. data/spec/unit/intercom/note_spec.rb +4 -10
  76. data/spec/unit/intercom/request_spec.rb +1 -1
  77. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  78. data/spec/unit/intercom/search_collection_proxy_spec.rb +32 -28
  79. data/spec/unit/intercom/section_spec.rb +32 -0
  80. data/spec/unit/intercom/segment_spec.rb +2 -2
  81. data/spec/unit/intercom/subscription_spec.rb +5 -6
  82. data/spec/unit/intercom/tag_spec.rb +22 -14
  83. data/spec/unit/intercom/team_spec.rb +2 -2
  84. data/spec/unit/intercom/traits/api_resource_spec.rb +107 -52
  85. data/spec/unit/intercom/user_spec.rb +224 -226
  86. data/spec/unit/intercom/visitor_spec.rb +49 -0
  87. data/spec/unit/intercom_spec.rb +5 -3
  88. metadata +34 -8
  89. data/lib/intercom/customer.rb +0 -10
  90. data/lib/intercom/service/customer.rb +0 -14
  91. data/spec/unit/intercom/visitors_spec.rb +0 -61
@@ -9,7 +9,7 @@ describe 'Intercom::Request', '#execute' do
9
9
  let(:default_body) { { data: "test" }.to_json }
10
10
 
11
11
  def execute!
12
- req.execute(uri, username: 'ted', secret: '')
12
+ req.execute(uri, token: 'test-token')
13
13
  end
14
14
 
15
15
  it 'should call sleep for rate limit error three times and raise a rate limit error otherwise' do
@@ -1,56 +1,57 @@
1
- require "spec_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
2
4
 
3
5
  describe Intercom::ScrollCollectionProxy do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
6
+ let(:client) { Intercom::Client.new(token: 'token') }
5
7
 
6
- it "stops iterating if no users returned" do
7
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(false))
8
- emails = []
9
- client.users.scroll.each { |user| emails << user.email }
10
- emails.must_equal %W()
8
+ it 'stops iterating if no companies returned' do
9
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(false))
10
+ names = []
11
+ client.companies.scroll.each { |company| names << company.name }
12
+ _(names).must_equal %w[]
11
13
  end
12
14
 
13
- it "keeps iterating if users returned" do
14
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(true))
15
- client.expects(:get).with('/users/scroll', {:scroll_param => 'da6bbbac-25f6-4f07-866b-b911082d7'}).returns(users_scroll(false))
16
- emails = []
17
- client.users.scroll.each { |user| emails << user.email }
15
+ it 'keeps iterating if companies returned' do
16
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(true))
17
+ client.expects(:get).with('/companies/scroll', scroll_param: 'da6bbbac-25f6-4f07-866b-b911082d7').returns(companies_scroll(false))
18
+ names = []
19
+ client.companies.scroll.each { |company| names << company.name }
18
20
  end
19
21
 
20
- it "supports indexed array access" do
21
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(true))
22
- client.users.scroll[0].email.must_equal 'user1@example.com'
22
+ it 'supports indexed array access' do
23
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(true))
24
+ _(client.companies.scroll[0].name).must_equal 'company1'
23
25
  end
24
26
 
25
- it "supports map" do
26
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(true))
27
- client.expects(:get).with('/users/scroll', {:scroll_param => 'da6bbbac-25f6-4f07-866b-b911082d7'}).returns(users_scroll(false))
28
- emails = client.users.scroll.map { |user| user.email }
29
- emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
27
+ it 'supports map' do
28
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(true))
29
+ client.expects(:get).with('/companies/scroll', scroll_param: 'da6bbbac-25f6-4f07-866b-b911082d7').returns(companies_scroll(false))
30
+ names = client.companies.scroll.map(&:name)
31
+ _(names).must_equal %w[company1 company2 company3]
30
32
  end
31
33
 
32
- it "returns one page scroll" do
33
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(true))
34
- scroll = client.users.scroll.next
35
- emails = []
36
- scroll.records.each {|usr| emails << usr.email}
37
- emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
34
+ it 'returns one page scroll' do
35
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(true))
36
+ scroll = client.companies.scroll.next
37
+ names = []
38
+ scroll.records.each { |usr| names << usr.name }
39
+ _(names).must_equal %w[company1 company2 company3]
38
40
  end
39
41
 
40
- it "keeps iterating if called with scroll_param" do
41
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(true))
42
- client.expects(:get).with('/users/scroll', {:scroll_param => 'da6bbbac-25f6-4f07-866b-b911082d7'}).returns(users_scroll(true))
43
- scroll = client.users.scroll.next
44
- scroll = client.users.scroll.next('da6bbbac-25f6-4f07-866b-b911082d7')
45
- emails =[]
46
- scroll.records.each {|usr| puts usr.email}
42
+ it 'keeps iterating if called with scroll_param' do
43
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(true))
44
+ client.expects(:get).with('/companies/scroll', scroll_param: 'da6bbbac-25f6-4f07-866b-b911082d7').returns(companies_scroll(true))
45
+ scroll = client.companies.scroll.next
46
+ scroll = client.companies.scroll.next('da6bbbac-25f6-4f07-866b-b911082d7')
47
+ scroll.records.each(&:name)
47
48
  end
48
49
 
49
- it "works with an empty list" do
50
- client.expects(:get).with("/users/scroll", '').returns(users_scroll(false))
51
- scroll = client.users.scroll.next
52
- emails = []
53
- scroll.records.each {|usr| emails << usr.email}
54
- emails.must_equal %W()
50
+ it 'works with an empty list' do
51
+ client.expects(:get).with('/companies/scroll', '').returns(companies_scroll(false))
52
+ scroll = client.companies.scroll.next
53
+ names = []
54
+ scroll.records.each { |usr| names << usr.name }
55
+ _(names).must_equal %w[]
55
56
  end
56
57
  end
@@ -1,56 +1,60 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Intercom::SearchCollectionProxy do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
- it "send query to the customer search endpoint" do
7
- client.expects(:post).with("/customers/search", { query: {} }). returns(page_of_customers(false))
8
- client.customers.search(query: {}).first
6
+ it "sends query to the contact search endpoint" do
7
+ client.expects(:post).with("/contacts/search", { query: {} }).returns(page_of_contacts(false))
8
+ client.contacts.search(query: {}).first
9
9
  end
10
10
 
11
- it "send query to the customer search endpoint with sort_field" do
12
- client.expects(:post).with("/customers/search", { query: {}, sort: { field: "name" } }). returns(page_of_customers(false))
13
- client.customers.search(query: {}, sort_field: "name").first
11
+ it "sends query to the conversation search endpoint" do
12
+ client.expects(:post).with("/conversations/search", { query: {} }).returns(test_conversation_list)
13
+ client.conversations.search(query: {}).first
14
14
  end
15
15
 
16
- it "send query to the customer search endpoint with sort_field and sort_order" do
17
- client.expects(:post).with("/customers/search", { query: {}, sort: { field: "name", order: "ascending" } }). returns(page_of_customers(false))
18
- client.customers.search(query: {}, sort_field: "name", sort_order: "ascending").first
16
+ it "sends query to the contact search endpoint with sort_field" do
17
+ client.expects(:post).with("/contacts/search", { query: {}, sort: { field: "name" } }).returns(page_of_contacts(false))
18
+ client.contacts.search(query: {}, sort_field: "name").first
19
19
  end
20
20
 
21
- it "send query to the customer search endpoint with per_page" do
22
- client.expects(:post).with("/customers/search", { query: {}, pagination: { per_page: 10 }}). returns(page_of_customers(false))
23
- client.customers.search(query: {}, per_page: 10).first
21
+ it "sends query to the contact search endpoint with sort_field and sort_order" do
22
+ client.expects(:post).with("/contacts/search", { query: {}, sort: { field: "name", order: "ascending" } }).returns(page_of_contacts(false))
23
+ client.contacts.search(query: {}, sort_field: "name", sort_order: "ascending").first
24
24
  end
25
25
 
26
- it "send query to the customer search endpoint with starting_after" do
27
- client.expects(:post).with("/customers/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}). returns(page_of_customers(false))
28
- client.customers.search(query: {}, starting_after: "EnCrYpTeDsTrInG").first
26
+ it "sends query to the contact search endpoint with per_page" do
27
+ client.expects(:post).with("/contacts/search", { query: {}, pagination: { per_page: 10 }}).returns(page_of_contacts(false))
28
+ client.contacts.search(query: {}, per_page: 10).first
29
+ end
30
+
31
+ it "sends query to the contact search endpoint with starting_after" do
32
+ client.expects(:post).with("/contacts/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}).returns(page_of_contacts(false))
33
+ client.contacts.search(query: {}, starting_after: "EnCrYpTeDsTrInG").first
29
34
  end
30
35
 
31
36
  it "stops iterating if no starting_after value" do
32
- client.expects(:post).with("/customers/search", { query: {} }). returns(page_of_customers(false))
37
+ client.expects(:post).with("/contacts/search", { query: {} }).returns(page_of_contacts(false))
33
38
  emails = []
34
- client.customers.search(query: {}).each { |user| emails << user.email }
35
- emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
39
+ client.contacts.search(query: {}).each { |contact| emails << contact.email }
40
+ _(emails).must_equal %w[test1@example.com test2@example.com test3@example.com]
36
41
  end
37
42
 
38
43
  it "keeps iterating if starting_after value" do
39
- client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(true))
40
- client.expects(:post).with("/customers/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}).returns(page_of_customers(false))
44
+ client.expects(:post).with("/contacts/search", { query: {} }).returns(page_of_contacts(true))
45
+ client.expects(:post).with("/contacts/search", { query: {}, pagination: { starting_after: "EnCrYpTeDsTrInG" }}).returns(page_of_contacts(false))
41
46
  emails = []
42
- client.customers.search(query: {}).each { |user| emails << user.email }
47
+ client.contacts.search(query: {}).each { |contact| emails << contact.email }
43
48
  end
44
49
 
45
50
  it "supports indexed array access" do
46
- client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(false))
47
- client.customers.search(query: {})[0].email.must_equal 'user1@example.com'
51
+ client.expects(:post).with("/contacts/search", { query: {} }).returns(page_of_contacts(false))
52
+ _(client.contacts.search(query: {})[0].email).must_equal 'test1@example.com'
48
53
  end
49
54
 
50
55
  it "supports map" do
51
- client.expects(:post).with("/customers/search", { query: {} }).returns(page_of_customers(false))
52
- emails = client.customers.search(query: {}).map { |user| user.email }
53
- emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
56
+ client.expects(:post).with("/contacts/search", { query: {} }).returns(page_of_contacts(false))
57
+ emails = client.contacts.search(query: {}).map { |contact| contact.email }
58
+ _(emails).must_equal %w[test1@example.com test2@example.com test3@example.com]
54
59
  end
55
-
56
60
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Intercom::Section do
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
+
6
+ it 'creates a section' do
7
+ client.expects(:post).with('/help_center/sections', { 'name' => 'Section 1', 'parent_id' => '1' }).returns(test_section)
8
+ client.sections.create(:name => 'Section 1', :parent_id => '1')
9
+ end
10
+
11
+ it 'lists sections' do
12
+ client.expects(:get).with('/help_center/sections', {}).returns(test_section_list)
13
+ client.sections.all.each { |t| }
14
+ end
15
+
16
+ it 'finds a section' do
17
+ client.expects(:get).with('/help_center/sections/1', {}).returns(test_section)
18
+ client.sections.find(id: '1')
19
+ end
20
+
21
+ it 'updates a section' do
22
+ section = Intercom::Section.new(id: '12345')
23
+ client.expects(:put).with('/help_center/sections/12345', {})
24
+ client.sections.save(section)
25
+ end
26
+
27
+ it 'deletes a section' do
28
+ section = Intercom::Section.new(id: '12345')
29
+ client.expects(:delete).with('/help_center/sections/12345', {})
30
+ client.sections.delete(section)
31
+ end
32
+ end
@@ -2,11 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe "Intercom::Segment" do
4
4
 
5
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
5
+ let(:client) { Intercom::Client.new(token: 'token') }
6
6
 
7
7
  it 'lists segments' do
8
8
  client.expects(:get).with('/segments', {}).returns(segment_list)
9
9
  segments = client.segments.all.to_a
10
- segments[0].name.must_equal('Active')
10
+ _(segments[0].name).must_equal('Active')
11
11
  end
12
12
  end
@@ -1,20 +1,19 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Intercom::Subscription" do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
6
  it "gets a subscription" do
7
7
  client.expects(:get).with("/subscriptions/nsub_123456789", {}).returns(test_subscription)
8
8
  subscription = client.subscriptions.find(:id => "nsub_123456789")
9
- subscription.request.topics[0].must_equal "user.created"
10
- subscription.request.topics[1].must_equal "conversation.user.replied"
9
+ _(subscription.request.topics[0]).must_equal "user.created"
10
+ _(subscription.request.topics[1]).must_equal "conversation.user.replied"
11
11
  end
12
12
 
13
13
  it "creates a subscription" do
14
14
  client.expects(:post).with("/subscriptions", {'url' => "http://example.com", 'topics' => ["user.created"]}).returns(test_subscription)
15
15
  subscription = client.subscriptions.create(:url => "http://example.com", :topics => ["user.created"])
16
- subscription.request.topics[0].must_equal "user.created"
17
- subscription.request.url.must_equal "http://example.com"
16
+ _(subscription.request.topics[0]).must_equal "user.created"
17
+ _(subscription.request.url).must_equal "http://example.com"
18
18
  end
19
-
20
19
  end
@@ -1,23 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
- describe "Intercom::Tag" do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
5
+ describe 'Intercom::Tag' do
6
+ let(:client) { Intercom::Client.new(token: 'token') }
7
+
8
+ it 'creates a tag' do
9
+ client.expects(:post).with('/tags', 'name' => 'Test Tag').returns(test_tag)
10
+ tag = client.tags.create(name: 'Test Tag')
11
+ _(tag.name).must_equal 'Test Tag'
12
+ end
5
13
 
6
- it "creates a tag" do
7
- client.expects(:post).with("/tags", {'name' => "Test Tag"}).returns(test_tag)
8
- tag = client.tags.create(:name => "Test Tag")
9
- tag.name.must_equal "Test Tag"
14
+ it 'finds a tag by id' do
15
+ client.expects(:get).with('/tags/4f73428b5e4dfc000b000112', {}).returns(test_tag)
16
+ tag = client.tags.find(id: '4f73428b5e4dfc000b000112')
17
+ _(tag.name).must_equal 'Test Tag'
10
18
  end
11
19
 
12
- it "tags users" do
13
- client.expects(:post).with("/tags", {'name' => "Test Tag", 'users' => [ { user_id: 'abc123' }, { user_id: 'def456' } ], 'tag_or_untag' => 'tag'}).returns(test_tag)
14
- tag = client.tags.tag(:name => "Test Tag", :users => [ { user_id: "abc123" }, { user_id: "def456" } ] )
15
- tag.name.must_equal "Test Tag"
16
- tag.tagged_user_count.must_equal 2
20
+ it 'tags companies' do
21
+ client.expects(:post).with('/tags', 'name' => 'Test Tag', 'companies' => [{ company_id: 'abc123' }, { company_id: 'def456' }], 'tag_or_untag' => 'tag').returns(test_tag)
22
+ tag = client.tags.tag(name: 'Test Tag', companies: [{ company_id: 'abc123' }, { company_id: 'def456' }])
23
+ _(tag.name).must_equal 'Test Tag'
24
+ _(tag.tagged_company_count).must_equal 2
17
25
  end
18
26
 
19
- it 'untags users' do
20
- client.expects(:post).with("/tags", {'name' => "Test Tag", 'users' => [ { user_id: 'abc123', untag: true }, { user_id: 'def456', untag: true } ], 'tag_or_untag' => 'untag'}).returns(test_tag)
21
- client.tags.untag(:name => "Test Tag", :users => [ { user_id: "abc123" }, { user_id: "def456" } ])
27
+ it 'untags companies' do
28
+ client.expects(:post).with('/tags', 'name' => 'Test Tag', 'companies' => [{ company_id: 'abc123', untag: true }, { company_id: 'def456', untag: true }], 'tag_or_untag' => 'untag').returns(test_tag)
29
+ client.tags.untag(name: 'Test Tag', companies: [{ company_id: 'abc123' }, { company_id: 'def456' }])
22
30
  end
23
31
  end
@@ -1,12 +1,12 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "Intercom::Team" do
4
- let (:client) { Intercom::Client.new(token: 'token') }
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
6
  it "returns a CollectionProxy for all without making any requests" do
7
7
  client.expects(:execute_request).never
8
8
  all = client.teams.all
9
- all.must_be_instance_of(Intercom::ClientCollectionProxy)
9
+ _(all).must_be_instance_of(Intercom::ClientCollectionProxy)
10
10
  end
11
11
 
12
12
  it 'gets an team list' do
@@ -1,98 +1,115 @@
1
- require "spec_helper"
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
2
4
 
3
5
  describe Intercom::Traits::ApiResource do
4
6
  let(:object_json) do
5
- {"type"=>"company",
6
- "id"=>"aaaaaaaaaaaaaaaaaaaaaaaa",
7
- "app_id"=>"some-app-id",
8
- "name"=>"SuperSuite",
9
- "plan_id"=>1,
10
- "remote_company_id"=>"8",
11
- "remote_created_at"=>103201,
12
- "created_at"=>1374056196,
13
- "user_count"=>1,
14
- "custom_attributes"=>{},
15
- "metadata"=>{
16
- "type"=>"user",
17
- "color"=>"cyan"
18
- }}
7
+ { 'type' => 'company',
8
+ 'id' => 'aaaaaaaaaaaaaaaaaaaaaaaa',
9
+ 'app_id' => 'some-app-id',
10
+ 'name' => 'SuperSuite',
11
+ 'plan_id' => 1,
12
+ 'remote_company_id' => '8',
13
+ 'remote_created_at' => 103_201,
14
+ 'created_at' => 1_374_056_196,
15
+ 'user_count' => 1,
16
+ 'custom_attributes' => {},
17
+ 'metadata' => {
18
+ 'type' => 'user',
19
+ 'color' => 'cyan'
20
+ },
21
+ 'nested_fields' => {
22
+ 'type' => 'nested_fields_content',
23
+ 'field_1' => {
24
+ 'type' => 'field_content',
25
+ 'name' => 'Nested Field'
26
+ }
27
+ }
28
+ }
19
29
  end
20
30
 
21
31
  let(:object_hash) do
22
32
  {
23
- type: "company",
24
- id: "aaaaaaaaaaaaaaaaaaaaaaaa",
25
- app_id: "some-app-id",
26
- name: "SuperSuite",
33
+ type: 'company',
34
+ id: 'aaaaaaaaaaaaaaaaaaaaaaaa',
35
+ app_id: 'some-app-id',
36
+ name: 'SuperSuite',
27
37
  plan_id: 1,
28
- remote_company_id: "8",
29
- remote_created_at: 103201,
30
- created_at: 1374056196,
38
+ remote_company_id: '8',
39
+ remote_created_at: 103_201,
40
+ created_at: 1_374_056_196,
31
41
  user_count: 1,
32
- custom_attributes: { type: "ping" },
42
+ custom_attributes: { type: 'ping' },
33
43
  metadata: {
34
- type: "user",
35
- color: "cyan"
44
+ type: 'user',
45
+ color: 'cyan'
46
+ },
47
+ nested_fields: {
48
+ type: 'nested_fields_content',
49
+ field_1: {
50
+ type: 'field_content',
51
+ name: 'Nested Field'
52
+ }
36
53
  }
37
54
  }
38
55
  end
39
56
 
40
- let(:api_resource) { DummyClass.new.extend(Intercom::Traits::ApiResource)}
57
+ let(:api_resource) { DummyClass.new.extend(Intercom::Traits::ApiResource) }
41
58
 
42
59
  before(:each) { api_resource.from_response(object_json) }
43
60
 
44
- it "coerces time on parsing json" do
45
- assert_equal Time.at(1374056196), api_resource.created_at
61
+ it 'coerces time on parsing json' do
62
+ assert_equal Time.at(1_374_056_196), api_resource.created_at
46
63
  end
47
64
 
48
- it "exposes string" do
49
- assert_equal Time.at(1374056196), api_resource.created_at
65
+ it 'exposes string' do
66
+ assert_equal Time.at(1_374_056_196), api_resource.created_at
50
67
  end
51
68
 
52
69
  it "treats 'metadata' as a plain hash, not a typed object" do
53
70
  assert_equal Hash, api_resource.metadata.class
54
71
  end
55
72
 
56
- it "dynamically defines accessors when a non-existent property is called that looks like a setter" do
57
- api_resource.wont_respond_to :spiders
73
+ it 'dynamically defines accessors when a non-existent property is called that looks like a setter' do
74
+ _(api_resource).wont_respond_to :spiders
58
75
  api_resource.spiders = 4
59
- api_resource.must_respond_to :spiders
76
+ _(api_resource).must_respond_to :spiders
60
77
  end
61
78
 
62
- it "calls dynamically defined getter when asked" do
79
+ it 'calls dynamically defined getter when asked' do
63
80
  api_resource.foo = 4
64
81
  assert_equal 4, api_resource.foo
65
82
  end
66
83
 
67
- it "accepts unix timestamps into dynamically defined date setters" do
68
- api_resource.foo_at = 1401200468
69
- assert_equal 1401200468, api_resource.instance_variable_get(:@foo_at)
84
+ it 'accepts unix timestamps into dynamically defined date setters' do
85
+ api_resource.foo_at = 1_401_200_468
86
+ assert_equal 1_401_200_468, api_resource.instance_variable_get(:@foo_at)
70
87
  end
71
88
 
72
- it "exposes dates correctly for dynamically defined getters" do
73
- api_resource.foo_at = 1401200468
74
- assert_equal Time.at(1401200468), api_resource.foo_at
89
+ it 'exposes dates correctly for dynamically defined getters' do
90
+ api_resource.foo_at = 1_401_200_468
91
+ assert_equal Time.at(1_401_200_468), api_resource.foo_at
75
92
  end
76
93
 
77
- it "throws regular method missing error when non-existent getter is called that is backed by an instance variable" do
94
+ it 'throws regular method missing error when non-existent getter is called that is backed by an instance variable' do
78
95
  api_resource.instance_variable_set(:@bar, 'you cant see me')
79
- proc { api_resource.bar }.must_raise NoMethodError
96
+ _(proc { api_resource.bar }).must_raise NoMethodError
80
97
  end
81
98
 
82
- it "throws attribute not set error when non-existent getter is called that is not backed by an instance variable" do
83
- proc { api_resource.flubber }.must_raise Intercom::AttributeNotSetError
99
+ it 'throws attribute not set error when non-existent getter is called that is not backed by an instance variable' do
100
+ _(proc { api_resource.flubber }).must_raise Intercom::AttributeNotSetError
84
101
  end
85
102
 
86
- it "throws regular method missing error when non-existent method is called that cannot be an accessor" do
87
- proc { api_resource.flubber! }.must_raise NoMethodError
88
- proc { api_resource.flubber? }.must_raise NoMethodError
103
+ it 'throws regular method missing error when non-existent method is called that cannot be an accessor' do
104
+ _(proc { api_resource.flubber! }).must_raise NoMethodError
105
+ _(proc { api_resource.flubber? }).must_raise NoMethodError
89
106
  end
90
107
 
91
- it "throws regular method missing error when non-existent setter is called with multiple arguments" do
92
- proc { api_resource.send(:flubber=, 'a', 'b') }.must_raise NoMethodError
108
+ it 'throws regular method missing error when non-existent setter is called with multiple arguments' do
109
+ _(proc { api_resource.send(:flubber=, 'a', 'b') }).must_raise NoMethodError
93
110
  end
94
111
 
95
- it "an initialized ApiResource is equal to one generated from a response" do
112
+ it 'an initialized ApiResource is equal to one generated from a response' do
96
113
  class ConcreteApiResource; include Intercom::Traits::ApiResource; end
97
114
  initialized_api_resource = ConcreteApiResource.new(object_json)
98
115
  except(object_json, 'type').keys.each do |attribute|
@@ -100,17 +117,55 @@ describe Intercom::Traits::ApiResource do
100
117
  end
101
118
  end
102
119
 
103
- it "initialized ApiResource using hash is equal to one generated from response" do
120
+ it 'initialized ApiResource using hash is equal to one generated from response' do
104
121
  class ConcreteApiResource; include Intercom::Traits::ApiResource; end
105
122
 
106
123
  api_resource.from_hash(object_hash)
107
124
  initialized_api_resource = ConcreteApiResource.new(object_hash)
108
-
109
125
  except(object_json, 'type').keys.each do |attribute|
110
126
  assert_equal initialized_api_resource.send(attribute), api_resource.send(attribute)
111
127
  end
112
128
  end
113
129
 
130
+ describe 'correctly equates two resources' do
131
+ class DummyResource; include Intercom::Traits::ApiResource; end
132
+
133
+ specify 'if each resource has the same class and same value' do
134
+ api_resource1 = DummyResource.new(object_json)
135
+ api_resource2 = DummyResource.new(object_json)
136
+ assert_equal (api_resource1 == api_resource2), true
137
+ end
138
+
139
+ specify 'if each resource has the same class and different value' do
140
+ object2_json = object_json.merge('id' => 'bbbbbb')
141
+ api_resource1 = DummyResource.new(object_json)
142
+ api_resource2 = DummyResource.new(object2_json)
143
+ assert_equal (api_resource1 == api_resource2), false
144
+ end
145
+
146
+ specify 'if each resource has a different class' do
147
+ dummy_resource = DummyResource.new(object_json)
148
+ assert_equal (dummy_resource == api_resource), false
149
+ end
150
+ end
151
+
152
+ it 'correctly generates submittable hash when no updates' do
153
+ assert_equal api_resource.to_submittable_hash, {}
154
+ end
155
+
156
+ it 'correctly generates submittable hash when there are updates' do
157
+ api_resource.name = 'SuperSuite updated'
158
+ api_resource.nested_fields.field_1.name = 'Updated Name'
159
+ assert_equal api_resource.to_submittable_hash, {
160
+ 'name' => 'SuperSuite updated',
161
+ 'nested_fields' => {
162
+ 'field_1' => {
163
+ 'name' => 'Updated Name'
164
+ }
165
+ }
166
+ }
167
+ end
168
+
114
169
  def except(h, *keys)
115
170
  keys.each { |key| h.delete(key) }
116
171
  h