intercom 3.9.5 → 4.1.2

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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +355 -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 +22 -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 +38 -42
  35. data/lib/intercom/search_collection_proxy.rb +30 -65
  36. data/lib/intercom/section.rb +23 -0
  37. data/lib/intercom/segment.rb +4 -0
  38. data/lib/intercom/service/article.rb +20 -0
  39. data/lib/intercom/service/base_service.rb +7 -0
  40. data/lib/intercom/service/collection.rb +24 -0
  41. data/lib/intercom/service/company.rb +2 -12
  42. data/lib/intercom/service/contact.rb +31 -10
  43. data/lib/intercom/service/conversation.rb +12 -3
  44. data/lib/intercom/service/data_attribute.rb +20 -0
  45. data/lib/intercom/service/lead.rb +41 -0
  46. data/lib/intercom/service/note.rb +4 -8
  47. data/lib/intercom/service/section.rb +7 -0
  48. data/lib/intercom/service/subscription.rb +2 -2
  49. data/lib/intercom/service/tag.rb +9 -9
  50. data/lib/intercom/service/visitor.rb +17 -8
  51. data/lib/intercom/tag.rb +4 -0
  52. data/lib/intercom/traits/api_resource.rb +44 -18
  53. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  54. data/lib/intercom/user.rb +12 -3
  55. data/lib/intercom/utils.rb +13 -2
  56. data/lib/intercom/version.rb +1 -1
  57. data/lib/intercom/visitor.rb +0 -2
  58. data/spec/spec_helper.rb +843 -520
  59. data/spec/unit/intercom/admin_spec.rb +2 -2
  60. data/spec/unit/intercom/article_spec.rb +40 -0
  61. data/spec/unit/intercom/base_collection_proxy_spec.rb +30 -0
  62. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  63. data/spec/unit/intercom/client_spec.rb +25 -26
  64. data/spec/unit/intercom/collection_spec.rb +32 -0
  65. data/spec/unit/intercom/company_spec.rb +18 -14
  66. data/spec/unit/intercom/contact_spec.rb +363 -33
  67. data/spec/unit/intercom/conversation_spec.rb +55 -7
  68. data/spec/unit/intercom/count_spec.rb +4 -4
  69. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  70. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  71. data/spec/unit/intercom/event_spec.rb +9 -11
  72. data/spec/unit/intercom/job_spec.rb +24 -24
  73. data/spec/unit/intercom/lead_spec.rb +57 -0
  74. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  75. data/spec/unit/intercom/message_spec.rb +1 -1
  76. data/spec/unit/intercom/note_spec.rb +4 -10
  77. data/spec/unit/intercom/request_spec.rb +1 -1
  78. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  79. data/spec/unit/intercom/search_collection_proxy_spec.rb +32 -28
  80. data/spec/unit/intercom/section_spec.rb +32 -0
  81. data/spec/unit/intercom/segment_spec.rb +2 -2
  82. data/spec/unit/intercom/subscription_spec.rb +5 -6
  83. data/spec/unit/intercom/tag_spec.rb +22 -14
  84. data/spec/unit/intercom/team_spec.rb +2 -2
  85. data/spec/unit/intercom/traits/api_resource_spec.rb +107 -52
  86. data/spec/unit/intercom/user_spec.rb +224 -226
  87. data/spec/unit/intercom/visitor_spec.rb +49 -0
  88. data/spec/unit/intercom_spec.rb +5 -3
  89. metadata +37 -11
  90. data/lib/intercom/customer.rb +0 -10
  91. data/lib/intercom/service/customer.rb +0 -14
  92. 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