cogniteev-intercom 2.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +13 -0
  5. data/MIT-LICENSE +21 -0
  6. data/README.md +378 -0
  7. data/Rakefile +21 -0
  8. data/changes.txt +168 -0
  9. data/intercom.gemspec +28 -0
  10. data/lib/data/cacert.pem +3965 -0
  11. data/lib/ext/sliceable_hash.rb +16 -0
  12. data/lib/intercom.rb +176 -0
  13. data/lib/intercom/admin.rb +9 -0
  14. data/lib/intercom/api_operations/convert.rb +19 -0
  15. data/lib/intercom/api_operations/count.rb +16 -0
  16. data/lib/intercom/api_operations/delete.rb +15 -0
  17. data/lib/intercom/api_operations/find.rb +23 -0
  18. data/lib/intercom/api_operations/find_all.rb +33 -0
  19. data/lib/intercom/api_operations/list.rb +17 -0
  20. data/lib/intercom/api_operations/load.rb +16 -0
  21. data/lib/intercom/api_operations/save.rb +51 -0
  22. data/lib/intercom/collection_proxy.rb +71 -0
  23. data/lib/intercom/company.rb +29 -0
  24. data/lib/intercom/contact.rb +22 -0
  25. data/lib/intercom/conversation.rb +17 -0
  26. data/lib/intercom/count.rb +21 -0
  27. data/lib/intercom/errors.rb +61 -0
  28. data/lib/intercom/event.rb +11 -0
  29. data/lib/intercom/extended_api_operations/reply.rb +16 -0
  30. data/lib/intercom/extended_api_operations/tags.rb +14 -0
  31. data/lib/intercom/extended_api_operations/users.rb +17 -0
  32. data/lib/intercom/generic_handlers/base_handler.rb +22 -0
  33. data/lib/intercom/generic_handlers/count.rb +59 -0
  34. data/lib/intercom/generic_handlers/tag.rb +71 -0
  35. data/lib/intercom/generic_handlers/tag_find_all.rb +47 -0
  36. data/lib/intercom/lib/dynamic_accessors.rb +59 -0
  37. data/lib/intercom/lib/dynamic_accessors_on_method_missing.rb +53 -0
  38. data/lib/intercom/lib/flat_store.rb +31 -0
  39. data/lib/intercom/lib/typed_json_deserializer.rb +53 -0
  40. data/lib/intercom/message.rb +9 -0
  41. data/lib/intercom/note.rb +17 -0
  42. data/lib/intercom/notification.rb +20 -0
  43. data/lib/intercom/request.rb +166 -0
  44. data/lib/intercom/segment.rb +14 -0
  45. data/lib/intercom/subscription.rb +15 -0
  46. data/lib/intercom/tag.rb +23 -0
  47. data/lib/intercom/traits/api_resource.rb +132 -0
  48. data/lib/intercom/traits/dirty_tracking.rb +33 -0
  49. data/lib/intercom/traits/generic_handler_binding.rb +29 -0
  50. data/lib/intercom/traits/incrementable_attributes.rb +12 -0
  51. data/lib/intercom/user.rb +30 -0
  52. data/lib/intercom/utils.rb +62 -0
  53. data/lib/intercom/version.rb +3 -0
  54. data/spec/spec_helper.rb +308 -0
  55. data/spec/unit/intercom/admin_spec.rb +9 -0
  56. data/spec/unit/intercom/collection_proxy_spec.rb +34 -0
  57. data/spec/unit/intercom/company_spec.rb +23 -0
  58. data/spec/unit/intercom/contact_spec.rb +25 -0
  59. data/spec/unit/intercom/event_spec.rb +25 -0
  60. data/spec/unit/intercom/lib/flat_store_spec.rb +29 -0
  61. data/spec/unit/intercom/message_spec.rb +21 -0
  62. data/spec/unit/intercom/note_spec.rb +19 -0
  63. data/spec/unit/intercom/notification_spec.rb +68 -0
  64. data/spec/unit/intercom/request_spec.rb +16 -0
  65. data/spec/unit/intercom/subscription_spec.rb +18 -0
  66. data/spec/unit/intercom/tag_spec.rb +23 -0
  67. data/spec/unit/intercom/traits/api_resource_spec.rb +85 -0
  68. data/spec/unit/intercom/user_spec.rb +230 -0
  69. data/spec/unit/intercom_spec.rb +90 -0
  70. metadata +214 -0
@@ -0,0 +1,9 @@
1
+ require "spec_helper"
2
+
3
+ describe "Intercom::Admin" do
4
+ it "returns a CollectionProxy for all without making any requests" do
5
+ Intercom.expects(:execute_request).never
6
+ all = Intercom::Admin.all
7
+ all.must_be_instance_of(Intercom::CollectionProxy)
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe Intercom::CollectionProxy do
4
+
5
+ it "stops iterating if no next link" do
6
+ Intercom.expects(:get).with("/users", {}).returns(page_of_users(false))
7
+ emails = []
8
+ Intercom::User.all.each { |user| emails << user.email }
9
+ emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
10
+ end
11
+
12
+ it "keeps iterating if next link" do
13
+ Intercom.expects(:get).with("/users", {}).returns(page_of_users(true))
14
+ Intercom.expects(:get).with('https://api.intercom.io/users?per_page=50&page=2', {}).returns(page_of_users(false))
15
+ emails = []
16
+ Intercom::User.all.each { |user| emails << user.email }
17
+ end
18
+
19
+ it "supports indexed array access" do
20
+ Intercom.expects(:get).with("/users", {}).returns(page_of_users(false))
21
+ Intercom::User.all[0].email.must_equal 'user1@example.com'
22
+ end
23
+
24
+ it "supports map" do
25
+ Intercom.expects(:get).with("/users", {}).returns(page_of_users(false))
26
+ emails = Intercom::User.all.map { |user| user.email }
27
+ emails.must_equal %W(user1@example.com user2@example.com user3@example.com)
28
+ end
29
+
30
+ it "supports querying" do
31
+ Intercom.expects(:get).with("/users", {:tag_name => 'Taggart J'}).returns(page_of_users(false))
32
+ Intercom::User.find_all(:tag_name => 'Taggart J').map(&:email).must_equal %W(user1@example.com user2@example.com user3@example.com)
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Intercom::Company do
4
+
5
+ describe 'when no response raises error' do
6
+ it 'on find' do
7
+ Intercom.expects(:get).with("/companies", {:company_id => '4'}).returns(nil)
8
+ proc {Intercom::Company.find(:company_id => '4')}.must_raise Intercom::HttpError
9
+ end
10
+
11
+ it 'on find_all' do
12
+ Intercom.expects(:get).with("/companies", {}).returns(nil)
13
+ proc {Intercom::Company.all.each {|company| }}.must_raise Intercom::HttpError
14
+ end
15
+
16
+ it 'on load' do
17
+ Intercom.expects(:get).with("/companies", {:company_id => '4'}).returns({'type' =>'user', 'id' =>'aaaaaaaaaaaaaaaaaaaaaaaa', 'company_id' => '4', 'name' => 'MyCo'})
18
+ company = Intercom::Company.find(:company_id => '4')
19
+ Intercom.expects(:get).with('/companies/aaaaaaaaaaaaaaaaaaaaaaaa', {}).returns(nil)
20
+ proc {company.load}.must_raise Intercom::HttpError
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ describe "Intercom::Contact" do
4
+ it 'should not throw ArgumentErrors when there are no parameters' do
5
+ Intercom.expects(:post)
6
+ Intercom::Contact.create
7
+ end
8
+
9
+ describe 'converting' do
10
+ let(:contact) { Intercom::Contact.from_api(user_id: 'contact_id') }
11
+ let(:user) { Intercom::User.from_api(id: 'user_id') }
12
+
13
+ it do
14
+ Intercom.expects(:post).with(
15
+ "/contacts/convert",
16
+ {
17
+ contact: { user_id: contact.user_id },
18
+ user: user.identity_hash
19
+ }
20
+ ).returns(test_user)
21
+
22
+ contact.convert(user)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::Event" do
4
+
5
+ let(:user) {Intercom::User.new("email" => "jim@example.com", :user_id => "12345", :created_at => Time.now, :name => "Jim Bob")}
6
+ let(:created_time) {Time.now - 300}
7
+
8
+ it "creates an event with metadata" do
9
+ Intercom.expects(:post).with('/events', {'event_name' => 'Eventful 1', 'created_at' => created_time.to_i, 'email' => 'joe@example.com', 'metadata' => {'invitee_email' => 'pi@example.org', :invite_code => 'ADDAFRIEND', 'found_date' => 12909364407}}).returns(:status => 202)
10
+
11
+ Intercom::Event.create(:event_name => "Eventful 1", :created_at => created_time,
12
+ :email => 'joe@example.com',
13
+ :metadata => {
14
+ "invitee_email" => "pi@example.org",
15
+ :invite_code => "ADDAFRIEND",
16
+ "found_date" => 12909364407
17
+ })
18
+ end
19
+
20
+ it "creates an event without metadata" do
21
+ Intercom.expects(:post).with('/events', {'event_name' => 'sale of item', 'email' => 'joe@example.com'})
22
+ Intercom::Event.create(:event_name => "sale of item", :email => 'joe@example.com')
23
+ end
24
+
25
+ end
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe Intercom::Lib::FlatStore do
4
+ it "raises if you try to set or merge in nested hash structures" do
5
+ data = Intercom::Lib::FlatStore.new()
6
+ proc { data["thing"] = [1] }.must_raise ArgumentError
7
+ proc { data["thing"] = {1 => 2} }.must_raise ArgumentError
8
+ proc { Intercom::Lib::FlatStore.new({1 => {2 => 3}}) }.must_raise ArgumentError
9
+ end
10
+
11
+ it "raises if you try to use a non string key" do
12
+ data =Intercom::Lib::FlatStore.new()
13
+ proc { data[1] = "something" }.must_raise ArgumentError
14
+ end
15
+
16
+ it "sets and merges valid entries" do
17
+ data = Intercom::Lib::FlatStore.new()
18
+ data["a"] = 1
19
+ data[:b] = 2
20
+ data[:a].must_equal 1
21
+ data["b"].must_equal 2
22
+ data[:b].must_equal 2
23
+ data = Intercom::Lib::FlatStore.new({"a" => 1, :b => 2})
24
+ data["a"].must_equal 1
25
+ data[:a].must_equal 1
26
+ data["b"].must_equal 2
27
+ data[:b].must_equal 2
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::Message" do
4
+
5
+ let (:user) {Intercom::User.new("email" => "jim@example.com", :user_id => "12345", :created_at => Time.now, :name => "Jim Bob")}
6
+
7
+ it 'creates an user message with symbol keys' do
8
+ Intercom.expects(:post).with('/messages', {'from' => { :type => 'user', :email => 'jim@example.com'}, 'body' => 'halp'}).returns(:status => 200)
9
+ Intercom::Message.create(:from => { :type => "user", :email => "jim@example.com" }, :body => "halp")
10
+ end
11
+
12
+ it "creates an user message with string keys" do
13
+ Intercom.expects(:post).with('/messages', {'from' => { 'type' => 'user', 'email' => 'jim@example.com'}, 'body' => 'halp'}).returns(:status => 200)
14
+ Intercom::Message.create('from' => { 'type' => "user", 'email' => "jim@example.com" }, 'body' => "halp")
15
+ end
16
+
17
+ it "creates a admin message" do
18
+ Intercom.expects(:post).with('/messages', {'from' => { 'type' => "admin", 'id' => "1234" }, 'to' => { 'type' => 'user', 'id' => '5678' }, 'body' => 'halp', 'message_type' => 'inapp'}).returns(:status => 200)
19
+ Intercom::Message.create('from' => { 'type' => "admin", 'id' => "1234" }, :to => { 'type' => 'user', 'id' => '5678' }, 'body' => "halp", 'message_type' => 'inapp')
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe "notes" do
4
+ it "creates a note" do
5
+ Intercom.expects(:post).with("/notes", {"body" => "Note to leave on user"}).returns({"body" => "<p>Note to leave on user</p>", "created_at" => 1234567890})
6
+ note = Intercom::Note.create("body" => "Note to leave on user")
7
+ note.body.must_equal "<p>Note to leave on user</p>"
8
+ end
9
+
10
+ it "sets/gets allowed keys" do
11
+ params = {"body" => "Note body", "email" => "me@example.com", :user_id => "abc123"}
12
+ note = Intercom::Note.new(params)
13
+
14
+ note.to_hash.keys.sort.must_equal params.keys.map(&:to_s).sort
15
+ params.keys.each do | key|
16
+ note.send(key).must_equal params[key]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,68 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::Notification" do
4
+
5
+ it "converts notification hash to object" do
6
+ payload = Intercom::Notification.new(test_user_notification)
7
+ payload.must_be_instance_of Intercom::Notification
8
+ end
9
+
10
+ it "returns correct model type for User" do
11
+ payload = Intercom::Notification.new(test_user_notification)
12
+ payload.model_type.must_equal Intercom::User
13
+ end
14
+
15
+ it "returns correct User notification topic" do
16
+ payload = Intercom::Notification.new(test_user_notification)
17
+ payload.topic.must_equal "user.created"
18
+ end
19
+
20
+ it "returns instance of User" do
21
+ payload = Intercom::Notification.new(test_user_notification)
22
+ payload.model.must_be_instance_of Intercom::User
23
+ end
24
+
25
+ it "returns instance of Conversation" do
26
+ payload = Intercom::Notification.new(test_conversation_notification)
27
+ payload.model.must_be_instance_of Intercom::Conversation
28
+ end
29
+
30
+ it "returns correct model type for Conversation" do
31
+ payload = Intercom::Notification.new(test_conversation_notification)
32
+ payload.model_type.must_equal Intercom::Conversation
33
+ end
34
+
35
+ it "returns correct Conversation notification topic" do
36
+ payload = Intercom::Notification.new(test_conversation_notification)
37
+ payload.topic.must_equal "conversation.user.created"
38
+ end
39
+
40
+ it "returns inner User object for Conversation" do
41
+ payload = Intercom::Notification.new(test_conversation_notification)
42
+ payload.model.user.must_be_instance_of Intercom::User
43
+ end
44
+
45
+ it "returns inner User object with nil tags" do
46
+ user_notification = {
47
+ "type" => "notification_event",
48
+ "app_id" => "aa11aa",
49
+ "data" => {
50
+ "type" => "notification_event_data",
51
+ "item" => {
52
+ "type" => "user",
53
+ "id" => "abc123def",
54
+ "user_id" => "666",
55
+ "email" => "joe@example.com",
56
+ "name" => "Joe",
57
+ "tags" => {
58
+ "type" => "tag.list",
59
+ "tags" => nil
60
+ }
61
+ }
62
+ },
63
+ }
64
+ payload = Intercom::Notification.new(user_notification)
65
+ payload.model.tags.must_equal([])
66
+ end
67
+
68
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe 'Intercom::Request' do
5
+ it 'raises an error when a html error page rendered' do
6
+ response = OpenStruct.new(:code => 500)
7
+ req = Intercom::Request.new('path/', 'GET')
8
+ proc {req.parse_body('<html>somethjing</html>', response)}.must_raise(Intercom::ServerError)
9
+ end
10
+
11
+ it 'parse_body returns nil if decoded_body is nil' do
12
+ response = OpenStruct.new(:code => 500)
13
+ req = Intercom::Request.new('path/', 'GET')
14
+ req.parse_body(nil, response).must_equal(nil)
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::Subscription" do
4
+ it "gets a subscription" do
5
+ Intercom.expects(:get).with("/subscriptions/nsub_123456789", {}).returns(test_subscription)
6
+ subscription = Intercom::Subscription.find(:id => "nsub_123456789")
7
+ subscription.request.topics[0].must_equal "user.created"
8
+ subscription.request.topics[1].must_equal "conversation.user.replied"
9
+ end
10
+
11
+ it "creates a subscription" do
12
+ Intercom.expects(:post).with("/subscriptions", {'url' => "http://example.com", 'topics' => ["user.created"]}).returns(test_subscription)
13
+ subscription = Intercom::Subscription.create(:url => "http://example.com", :topics => ["user.created"])
14
+ subscription.request.topics[0].must_equal "user.created"
15
+ subscription.request.url.must_equal "http://example.com"
16
+ end
17
+
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Intercom::Tag" do
4
+ it "gets a tag" do
5
+ Intercom.expects(:get).with("/tags", {:name => "Test Tag"}).returns(test_tag)
6
+ tag = Intercom::Tag.find(:name => "Test Tag")
7
+ tag.name.must_equal "Test Tag"
8
+ end
9
+
10
+ it "creates a tag" do
11
+ Intercom.expects(:post).with("/tags", {'name' => "Test Tag"}).returns(test_tag)
12
+ tag = Intercom::Tag.create(:name => "Test Tag")
13
+ tag.name.must_equal "Test Tag"
14
+ end
15
+
16
+ it "tags users" do
17
+ Intercom.expects(:post).with("/tags", {'name' => "Test Tag", 'user_ids' => ["abc123", "def456"], 'tag_or_untag' => "tag"}).returns(test_tag)
18
+ tag = Intercom::Tag.create(:name => "Test Tag", :user_ids => ["abc123", "def456"], :tag_or_untag => "tag")
19
+ tag.name.must_equal "Test Tag"
20
+ tag.tagged_user_count.must_equal 2
21
+ end
22
+
23
+ end
@@ -0,0 +1,85 @@
1
+ require "spec_helper"
2
+
3
+ describe Intercom::Traits::ApiResource do
4
+ 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
+ end
16
+ let(:api_resource) { DummyClass.new.extend(Intercom::Traits::ApiResource)}
17
+
18
+ before(:each) { api_resource.from_response(object_json) }
19
+
20
+ it "does not set type on parsing json" do
21
+ api_resource.wont_respond_to :type
22
+ end
23
+
24
+ it "coerces time on parsing json" do
25
+ assert_equal Time.at(1374056196), api_resource.created_at
26
+ end
27
+
28
+ it "exposes string" do
29
+ assert_equal Time.at(1374056196), api_resource.created_at
30
+ end
31
+
32
+ it "dynamically defines accessors when a non-existent property is called that looks like a setter" do
33
+ api_resource.wont_respond_to :spiders
34
+ api_resource.spiders = 4
35
+ api_resource.must_respond_to :spiders
36
+ end
37
+
38
+ it "calls dynamically defined getter when asked" do
39
+ api_resource.foo = 4
40
+ assert_equal 4, api_resource.foo
41
+ end
42
+
43
+ it "accepts unix timestamps into dynamically defined date setters" do
44
+ api_resource.foo_at = 1401200468
45
+ assert_equal 1401200468, api_resource.instance_variable_get(:@foo_at)
46
+ end
47
+
48
+ it "exposes dates correctly for dynamically defined getters" do
49
+ api_resource.foo_at = 1401200468
50
+ assert_equal Time.at(1401200468), api_resource.foo_at
51
+ end
52
+
53
+ it "throws regular method missing error when non-existent getter is called that is backed by an instance variable" do
54
+ api_resource.instance_variable_set(:@bar, 'you cant see me')
55
+ proc { api_resource.bar }.must_raise NoMethodError
56
+ end
57
+
58
+ it "throws attribute not set error when non-existent getter is called that is not backed by an instance variable" do
59
+ proc { api_resource.flubber }.must_raise Intercom::AttributeNotSetError
60
+ end
61
+
62
+ it "throws regular method missing error when non-existent method is called that cannot be an accessor" do
63
+ proc { api_resource.flubber! }.must_raise NoMethodError
64
+ proc { api_resource.flubber? }.must_raise NoMethodError
65
+ end
66
+
67
+ it "throws regular method missing error when non-existent setter is called with multiple arguments" do
68
+ proc { api_resource.send(:flubber=, 'a', 'b') }.must_raise NoMethodError
69
+ end
70
+
71
+ it "an initialized ApiResource is equal to on generated from a response" do
72
+ class ConcreteApiResource; include Intercom::Traits::ApiResource; end
73
+ initialized_api_resource = ConcreteApiResource.new(object_json)
74
+ except(object_json, 'type').keys.each do |attribute|
75
+ assert_equal initialized_api_resource.send(attribute), api_resource.send(attribute)
76
+ end
77
+ end
78
+
79
+ def except(h, *keys)
80
+ keys.each { |key| h.delete(key) }
81
+ h
82
+ end
83
+
84
+ class DummyClass; end
85
+ end
@@ -0,0 +1,230 @@
1
+ require "spec_helper"
2
+
3
+ describe "Intercom::User" do
4
+ it "to_hash'es itself" do
5
+ created_at = Time.now
6
+ user = Intercom::User.new(:email => "jim@example.com", :user_id => "12345", :created_at => created_at, :name => "Jim Bob")
7
+ as_hash = user.to_hash
8
+ as_hash["email"].must_equal "jim@example.com"
9
+ as_hash["user_id"].must_equal "12345"
10
+ as_hash["created_at"].must_equal created_at.to_i
11
+ as_hash["name"].must_equal "Jim Bob"
12
+ end
13
+
14
+ it "presents created_at and last_impression_at as Date" do
15
+ now = Time.now
16
+ user = Intercom::User.from_api(:created_at => now, :last_impression_at => now)
17
+ user.created_at.must_be_kind_of Time
18
+ user.created_at.to_s.must_equal now.to_s
19
+ user.last_impression_at.must_be_kind_of Time
20
+ user.last_impression_at.to_s.must_equal now.to_s
21
+ end
22
+
23
+ it "is throws a Intercom::AttributeNotSetError on trying to access an attribute that has not been set" do
24
+ user = Intercom::User.new
25
+ proc { user.foo_property }.must_raise Intercom::AttributeNotSetError
26
+ end
27
+
28
+ it "presents a complete user record correctly" do
29
+ user = Intercom::User.from_api(test_user)
30
+ user.user_id.must_equal 'id-from-customers-app'
31
+ user.email.must_equal 'bob@example.com'
32
+ user.name.must_equal 'Joe Schmoe'
33
+ user.app_id.must_equal 'the-app-id'
34
+ user.session_count.must_equal 123
35
+ user.created_at.to_i.must_equal 1401970114
36
+ user.remote_created_at.to_i.must_equal 1393613864
37
+ user.updated_at.to_i.must_equal 1401970114
38
+
39
+ user.avatar.must_be_kind_of Intercom::Avatar
40
+ user.avatar.image_url.must_equal 'https://graph.facebook.com/1/picture?width=24&height=24'
41
+
42
+ user.companies.must_be_kind_of Array
43
+ user.companies.size.must_equal 1
44
+ user.companies[0].must_be_kind_of Intercom::Company
45
+ user.companies[0].company_id.must_equal "123"
46
+ user.companies[0].id.must_equal "bbbbbbbbbbbbbbbbbbbbbbbb"
47
+ user.companies[0].app_id.must_equal "the-app-id"
48
+ user.companies[0].name.must_equal "Company 1"
49
+ user.companies[0].remote_created_at.to_i.must_equal 1390936440
50
+ user.companies[0].created_at.to_i.must_equal 1401970114
51
+ user.companies[0].updated_at.to_i.must_equal 1401970114
52
+ user.companies[0].last_request_at.to_i.must_equal 1401970113
53
+ user.companies[0].monthly_spend.must_equal 0
54
+ user.companies[0].session_count.must_equal 0
55
+ user.companies[0].user_count.must_equal 1
56
+ user.companies[0].tag_ids.must_equal []
57
+
58
+ user.custom_attributes.must_be_kind_of Intercom::Lib::FlatStore
59
+ user.custom_attributes["a"].must_equal "b"
60
+ user.custom_attributes["b"].must_equal 2
61
+
62
+ user.social_profiles.size.must_equal 4
63
+ twitter_account = user.social_profiles.first
64
+ twitter_account.must_be_kind_of Intercom::SocialProfile
65
+ twitter_account.name.must_equal "twitter"
66
+ twitter_account.username.must_equal "abc"
67
+ twitter_account.url.must_equal "http://twitter.com/abc"
68
+
69
+ user.location_data.must_be_kind_of Intercom::LocationData
70
+ user.location_data.city_name.must_equal "Dublin"
71
+ user.location_data.continent_code.must_equal "EU"
72
+ user.location_data.country_name.must_equal "Ireland"
73
+ user.location_data.latitude.must_equal "90"
74
+ user.location_data.longitude.must_equal "10"
75
+ user.location_data.country_code.must_equal "IRL"
76
+
77
+ user.unsubscribed_from_emails.must_equal true
78
+ user.user_agent_data.must_equal "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"
79
+ end
80
+
81
+ it 'allows update_last_request_at' do
82
+ Intercom.expects(:post).with("/users", {"user_id" => "1224242", 'update_last_request_at' => true, "custom_attributes" => {}}).returns({"user_id" => "i-1224242", "last_request_at" => 1414509439})
83
+ Intercom::User.create(user_id:'1224242', update_last_request_at:true)
84
+ end
85
+
86
+ it "allows easy setting of custom data" do
87
+ now = Time.now
88
+ user = Intercom::User.new
89
+ user.custom_attributes["mad"] = 123
90
+ user.custom_attributes["other"] = now.to_i
91
+ user.custom_attributes["thing"] = "yay"
92
+ user.to_hash["custom_attributes"].must_equal "mad" => 123, "other" => now.to_i, "thing" => "yay"
93
+ end
94
+
95
+ it "allows easy setting of multiple companies" do
96
+ user = Intercom::User.new()
97
+ companies = [
98
+ {"name" => "Intercom", "company_id" => "6"},
99
+ {"name" => "Test", "company_id" => "9"}
100
+ ]
101
+ user.companies = companies
102
+ user.to_hash["companies"].must_equal companies
103
+ end
104
+
105
+ it "rejects nested data structures in custom_attributes" do
106
+ user = Intercom::User.new()
107
+
108
+ proc { user.custom_attributes["thing"] = [1] }.must_raise(ArgumentError)
109
+ proc { user.custom_attributes["thing"] = {1 => 2} }.must_raise(ArgumentError)
110
+ proc { user.custom_attributes["thing"] = {1 => {2 => 3}} }.must_raise(ArgumentError)
111
+
112
+ user = Intercom::User.from_api(test_user)
113
+ proc { user.custom_attributes["thing"] = [1] }.must_raise(ArgumentError)
114
+ end
115
+
116
+ describe "incrementing custom_attributes fields" do
117
+ before :each do
118
+ @now = Time.now
119
+ @user = Intercom::User.new("email" => "jo@example.com", :user_id => "i-1224242", :custom_attributes => {"mad" => 123, "another" => 432, "other" => @now.to_i, :thing => "yay"})
120
+ end
121
+
122
+ it "increments up by 1 with no args" do
123
+ @user.increment("mad")
124
+ @user.to_hash["custom_attributes"]["mad"].must_equal 124
125
+ end
126
+
127
+ it "increments up by given value" do
128
+ @user.increment("mad", 4)
129
+ @user.to_hash["custom_attributes"]["mad"].must_equal 127
130
+ end
131
+
132
+ it "increments down by given value" do
133
+ @user.increment("mad", -1)
134
+ @user.to_hash["custom_attributes"]["mad"].must_equal 122
135
+ end
136
+
137
+ it "can increment new custom data fields" do
138
+ @user.increment("new_field", 3)
139
+ @user.to_hash["custom_attributes"]["new_field"].must_equal 3
140
+ end
141
+
142
+ it "can call increment on the same key twice and increment by 2" do
143
+ @user.increment("mad")
144
+ @user.increment("mad")
145
+ @user.to_hash["custom_attributes"]["mad"].must_equal 125
146
+ end
147
+ end
148
+
149
+ it "fetches a user" do
150
+ Intercom.expects(:get).with("/users", {"email" => "bo@example.com"}).returns(test_user)
151
+ user = Intercom::User.find("email" => "bo@example.com")
152
+ user.email.must_equal "bob@example.com"
153
+ user.name.must_equal "Joe Schmoe"
154
+ user.session_count.must_equal 123
155
+ end
156
+
157
+ it "saves a user (always sends custom_attributes)" do
158
+ user = Intercom::User.new("email" => "jo@example.com", :user_id => "i-1224242")
159
+ Intercom.expects(:post).with("/users", {"email" => "jo@example.com", "user_id" => "i-1224242", "custom_attributes" => {}}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
160
+ user.save
161
+ end
162
+
163
+ it "saves a user with a company" do
164
+ user = Intercom::User.new("email" => "jo@example.com", :user_id => "i-1224242", :company => {'company_id' => 6, 'name' => "Intercom"})
165
+ Intercom.expects(:post).with("/users", {'custom_attributes' => {}, "user_id" => "i-1224242", "email" => "jo@example.com", "company" => {"company_id" => 6, "name" => "Intercom"}}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
166
+ user.save
167
+ end
168
+
169
+ it "saves a user with a companies" do
170
+ user = Intercom::User.new("email" => "jo@example.com", :user_id => "i-1224242", :companies => [{'company_id' => 6, 'name' => "Intercom"}])
171
+ Intercom.expects(:post).with("/users", {'custom_attributes' => {}, "email" => "jo@example.com", "user_id" => "i-1224242", "companies" => [{"company_id" => 6, "name" => "Intercom"}]}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
172
+ user.save
173
+ end
174
+
175
+ it 'can save a user with a nil email' do
176
+ user = Intercom::User.new("email" => nil, :user_id => "i-1224242", :companies => [{'company_id' => 6, 'name' => "Intercom"}])
177
+ Intercom.expects(:post).with("/users", {'custom_attributes' => {}, "email" => nil, "user_id" => "i-1224242", "companies" => [{"company_id" => 6, "name" => "Intercom"}]}).returns({"email" => nil, "user_id" => "i-1224242"})
178
+ user.save
179
+ end
180
+
181
+ it "deletes a user" do
182
+ user = Intercom::User.new("id" => "1")
183
+ Intercom.expects(:delete).with("/users/1", {}).returns(user)
184
+ user.delete
185
+ end
186
+
187
+ it "can use User.create for convenience" do
188
+ Intercom.expects(:post).with("/users", {'custom_attributes' => {}, "email" => "jo@example.com", "user_id" => "i-1224242"}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
189
+ user = Intercom::User.create("email" => "jo@example.com", :user_id => "i-1224242")
190
+ user.email.must_equal "jo@example.com"
191
+ end
192
+
193
+ it "updates the @user with attributes as set by the server" do
194
+ Intercom.expects(:post).with("/users", {"email" => "jo@example.com", "user_id" => "i-1224242", 'custom_attributes' => {}}).returns({"email" => "jo@example.com", "user_id" => "i-1224242", "session_count" => 4})
195
+ user = Intercom::User.create("email" => "jo@example.com", :user_id => "i-1224242")
196
+ user.session_count.must_equal 4
197
+ end
198
+
199
+ it "allows setting dates to nil without converting them to 0" do
200
+ Intercom.expects(:post).with("/users", {"email" => "jo@example.com", 'custom_attributes' => {}, "remote_created_at" => nil}).returns({"email" => "jo@example.com"})
201
+ user = Intercom::User.create("email" => "jo@example.com", "remote_created_at" => nil)
202
+ user.remote_created_at.must_equal nil
203
+ end
204
+
205
+ it "sets/gets rw keys" do
206
+ params = {"email" => "me@example.com", :user_id => "abc123", "name" => "Bob Smith", "last_seen_ip" => "1.2.3.4", "last_seen_user_agent" => "ie6", "created_at" => Time.now}
207
+ user = Intercom::User.new(params)
208
+ custom_attributes = (params.keys + ['custom_attributes']).map(&:to_s).sort
209
+ user.to_hash.keys.sort.must_equal custom_attributes
210
+ params.keys.each do |key|
211
+ user.send(key).to_s.must_equal params[key].to_s
212
+ end
213
+ end
214
+
215
+ it "will allow extra attributes in response from api" do
216
+ user = Intercom::User.send(:from_api, {"new_param" => "some value"})
217
+ user.new_param.must_equal "some value"
218
+ end
219
+
220
+ it "returns a CollectionProxy for all without making any requests" do
221
+ Intercom.expects(:execute_request).never
222
+ all = Intercom::User.all
223
+ all.must_be_instance_of(Intercom::CollectionProxy)
224
+ end
225
+
226
+ it "returns the total number of users" do
227
+ Intercom::Count.expects(:user_count).returns('count_info')
228
+ Intercom::User.count
229
+ end
230
+ end