intercom 0.0.1 → 0.0.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.
@@ -0,0 +1,75 @@
1
+ require 'intercom/unix_timestamp_unwrapper'
2
+
3
+ module Intercom
4
+ class UserResource
5
+ include UnixTimestampUnwrapper
6
+
7
+ def initialize(attributes={})
8
+ self.attributes = attributes
9
+ end
10
+
11
+ def to_hash
12
+ UserResource.for_wire(@attributes)
13
+ end
14
+
15
+ def email
16
+ @attributes["email"]
17
+ end
18
+
19
+ def email=(email)
20
+ @attributes["email"]=email
21
+ end
22
+
23
+ def user_id
24
+ @attributes["user_id"]
25
+ end
26
+
27
+ def user_id=(user_id)
28
+ @attributes["user_id"] = user_id
29
+ end
30
+
31
+ def update_from_api_response(api_response)
32
+ api_response.each do |key, value|
33
+ setter_method = "#{key.to_s}="
34
+ if self.respond_to?(setter_method)
35
+ self.send(setter_method, value)
36
+ else
37
+ @attributes[key.to_s] = value
38
+ end
39
+ end
40
+ self
41
+ end
42
+
43
+ private
44
+
45
+ def attributes=(attributes={})
46
+ @attributes = {}
47
+ (attributes || {}).each do |key, value|
48
+ self.send("#{key.to_s}=", value)
49
+ end
50
+ end
51
+
52
+ def self.for_wire(object)
53
+ return object.for_wire if object.respond_to?(:for_wire)
54
+ return object.map { |item| for_wire(item) } if object.is_a?(Array)
55
+ return object.inject({}) { |result, (k, value)| result[k] = for_wire(value); result } if object.is_a?(Hash)
56
+ object
57
+ end
58
+
59
+ def self.from_api(api_response)
60
+ obj = self.new
61
+ obj.update_from_api_response(api_response)
62
+ end
63
+
64
+ def method_missing(method, *args, &block)
65
+ return @attributes[method.to_s] if @attributes.has_key?(method.to_s)
66
+ super
67
+ end
68
+
69
+ def self.requires_parameters(parameters, required)
70
+ missing = Array(required) - parameters.keys.map(&:to_s)
71
+ raise ArgumentError.new("Missing required parameters (#{missing.join(', ')}).") unless missing.empty?
72
+ end
73
+
74
+ end
75
+ end
@@ -1,3 +1,3 @@
1
- module Intercom
2
- VERSION = "0.0.1"
1
+ module Intercom #:nodoc:
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,28 @@
1
+ require 'intercom'
2
+ require 'minitest/autorun'
3
+
4
+ describe "api.intercom.io dummy data requests" do
5
+ before :each do
6
+ Intercom.app_id = "dummy-app-id"
7
+ Intercom.secret_key = "dummy-secret-key"
8
+ end
9
+
10
+ it "should get a user" do
11
+ user = Intercom::User.find(:email => "somebody@example.com")
12
+ user.name.must_equal "Somebody"
13
+ end
14
+
15
+ it "not found... " do
16
+ proc { Intercom::User.find(:email => "not-found@example.com") }.must_raise Intercom::ResourceNotFound
17
+ end
18
+
19
+ it "server error" do
20
+ proc { Intercom::User.find(:email => "server-error@example.com") }.must_raise Intercom::ServerError
21
+ end
22
+
23
+ it "authentication failure with bad api key" do
24
+ Intercom.app_id = "bad-app-id"
25
+ Intercom.secret_key = "bad-secret-key"
26
+ proc { Intercom::User.find(:email => "not-found@example.com") }.must_raise Intercom::AuthenticationError
27
+ end
28
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ describe "/v1/impressions" do
4
+ it "creates a good impression" do
5
+ Intercom.expects(:post).with("users/impressions", {"email" => "jo@example.com", "location" => "/some/path/in/my/app"}).returns({"unread_messages" => 10})
6
+ impression = Intercom::Impression.create("email" => "jo@example.com", "location" => "/some/path/in/my/app")
7
+ impression.unread_messages.must_equal 10
8
+ end
9
+
10
+ it "sets/gets allowed keys" do
11
+ params = {"user_ip" => "1.2.3.4", "user_agent" => "ie6", "location" => "/some/path/in/my/app", "email" => "me@example.com", :user_id => "abc123"}
12
+ impression = Intercom::Impression.new(params)
13
+ impression.to_hash.keys.sort.must_equal params.keys.map(&:to_s).sort
14
+ params.keys.each do | key|
15
+ impression.send(key).must_equal params[key]
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ require "spec_helper"
2
+
3
+ describe "/v1/messages_threads" do
4
+ it "loads messages for a user" do
5
+ Intercom.expects(:get).with("users/message_threads", {"email" => "bo@example.com"}).returns(test_messages)
6
+ message_threads = Intercom::MessageThread.find_all("email" => "bo@example.com")
7
+ message_threads.size.must_equal 2
8
+ message_threads.first.messages.size.must_equal 3
9
+ message_threads.first.messages[0].html.must_equal "<p>Hey Intercom, What is up?</p>\n"
10
+ end
11
+
12
+ it "loads message for a thread id" do
13
+ Intercom.expects(:get).with("users/message_threads", {"email" => "bo@example.com", "thread_id" => 123}).returns(test_message)
14
+ message_thread = Intercom::MessageThread.find("email" => "bo@example.com", "thread_id" => 123)
15
+ message_thread.messages.size.must_equal 3
16
+ end
17
+
18
+ it "creates a new message" do
19
+ Intercom.expects(:post).with("users/message_threads", {"email" => "jo@example.com", "body" => "Hello World"}).returns(test_message)
20
+ message_thread = Intercom::MessageThread.create("email" => "jo@example.com", "body" => "Hello World")
21
+ message_thread.messages.size.must_equal 3
22
+ end
23
+
24
+ it "creates a comment on existing thread" do
25
+ Intercom.expects(:post).with("users/message_threads", {"email" => "jo@example.com", "body" => "Hello World", "thread_id" => 123}).returns(test_message)
26
+ message_thread = Intercom::MessageThread.create("email" => "jo@example.com", "body" => "Hello World", "thread_id" => 123)
27
+ message_thread.messages.size.must_equal 3
28
+ end
29
+
30
+ it "marks a thread as read... " do
31
+ Intercom.expects(:put).with("users/message_threads", {"read" => true, "email" => "jo@example.com", "thread_id" => 123}).returns(test_message)
32
+ message_thread = Intercom::MessageThread.mark_as_read("email" => "jo@example.com", "thread_id" => 123)
33
+ message_thread.messages.size.must_equal 3
34
+ end
35
+
36
+ it "sets/gets allowed keys" do
37
+ params = {"email" => "me@example.com", :user_id => "abc123", "thread_id" => "123", "body" => "hello world", "read" => true}
38
+ message_thread = Intercom::MessageThread.new(params)
39
+ message_thread.to_hash.keys.sort.must_equal params.keys.map(&:to_s).sort
40
+ params.keys.each do | key|
41
+ message_thread.send(key).must_equal params[key]
42
+ end
43
+ end
44
+
45
+ it "should do automatic unwrapping of the timestamp " do
46
+ message_thread = Intercom::MessageThread.from_api(test_message)
47
+ message_thread.created_at.to_s.must_equal Time.at(test_message['created_at']).to_s
48
+ message_thread.updated_at.to_s.must_equal Time.at(test_message['updated_at']).to_s
49
+ end
50
+
51
+ describe "messages" do
52
+ it "has nice interface onto messages thread." do
53
+ message_thread = Intercom::MessageThread.from_api(test_message)
54
+ message_thread.messages.size.must_equal 3
55
+ message_thread.messages[0].created_at.to_s.must_equal Time.at(test_message['messages'][0]['created_at']).to_s
56
+ message_thread.messages[0].html.must_equal test_message['messages'][0]['html']
57
+ from_0 = test_message['messages'][0]['from']
58
+ message_thread.messages[0].from.email.must_equal from_0['email']
59
+ message_thread.messages[0].from.name.must_equal from_0['name']
60
+ message_thread.messages[0].from.admin?.must_equal from_0['is_admin']
61
+ message_thread.messages[0].from.user_id.must_equal from_0['user_id']
62
+ message_thread.messages[0].from.avatar_path_50.must_equal nil
63
+
64
+ message_thread.messages[1].created_at.must_equal Time.at(test_message['messages'][1]['created_at'])
65
+ message_thread.messages[1].html.must_equal test_message['messages'][1]['html']
66
+ from_1 = test_message['messages'][1]['from']
67
+ message_thread.messages[1].from.email.must_equal from_1['email']
68
+ message_thread.messages[1].from.name.must_equal from_1['name']
69
+ message_thread.messages[1].from.admin?.must_equal from_1['is_admin']
70
+ message_thread.messages[1].from.user_id.must_equal from_1['user_id']
71
+ message_thread.messages[1].from.avatar_path_50.must_equal from_1['avatar_path_50']
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ describe Intercom::UserResource do
4
+ describe "requires_params" do
5
+ it "raises if they are missing" do
6
+ params = {"a" => 1, "b" => 2}
7
+ Intercom::UserResource.requires_parameters(params, %W(a b))
8
+ expected_message = "Missing required parameters (c)."
9
+ proc { Intercom::UserResource.requires_parameters(params, %W(a b c)) }.must_raise ArgumentError, expected_message
10
+ capture_exception { Intercom::UserResource.requires_parameters(params, %W(a b c)) }.message.must_equal expected_message
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,133 @@
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 ok on missing methods" do
24
+ user = Intercom::User.new
25
+ user.created_at.must_be_nil
26
+ user.last_impression_at.must_be_nil
27
+ user.email.must_be_nil
28
+ user.social_profiles.must_equal([])
29
+ end
30
+
31
+ it "presents a complete user record correctly" do
32
+ user = Intercom::User.from_api(test_user)
33
+ user.session_count.must_equal 123
34
+ user.social_profiles.size.must_equal 4
35
+ twitter_account = user.social_profiles.first
36
+ twitter_account.must_be_kind_of Intercom::SocialProfile
37
+ twitter_account.type.must_equal "twitter"
38
+ twitter_account.username.must_equal "abc"
39
+ twitter_account.url.must_equal "http://twitter.com/abc"
40
+ user.custom_data["a"].must_equal "b"
41
+ user.custom_data["b"].must_equal 2
42
+ user.relationship_score.must_equal 90
43
+ user.last_seen_ip.must_equal "1.2.3.4"
44
+ user.last_seen_user_agent.must_equal "Mozilla blah blah ie6"
45
+ end
46
+
47
+ it "has read-only social accounts" do
48
+ user = Intercom::User.new(:social_profiles => [:url => "http://twitter.com/abc", "username" => "abc", "type" => "twitter"])
49
+ user.social_profiles.size.must_equal 1
50
+ twitter = user.social_profiles.first
51
+ twitter.type.must_equal "twitter"
52
+ twitter.url.must_equal "http://twitter.com/abc"
53
+ twitter.username.must_equal "abc"
54
+ user.to_hash["social_profiles"].must_equal nil
55
+ proc { user.social_profiles << "a" }.must_raise RuntimeError, "can't modify frozen array"
56
+ proc { Intercom::User.new.social_profiles << "a" }.must_raise RuntimeError, "can't modify frozen array"
57
+ end
58
+
59
+ it "has read-only location data" do
60
+ Intercom::User.new.location_data.must_equal({})
61
+ user = Intercom::User.new(:location_data => {"city" => "Dublin"})
62
+ user.location_data.must_equal({"city" => "Dublin"})
63
+ proc { user.location_data["change"] = "123" }.must_raise RuntimeError, "can't modify frozen hash"
64
+ user.to_hash["location_data"].must_equal nil
65
+ end
66
+
67
+ it "allows easy setting of custom data" do
68
+ now = Time.now
69
+ user = Intercom::User.new()
70
+ user.custom_data["mad"] = 123
71
+ user.custom_data["other"] = now
72
+ user.custom_data["thing"] = "yay"
73
+ user.to_hash["custom_data"].must_equal "mad" => 123, "other" => now, "thing" => "yay"
74
+ end
75
+
76
+ it "rejects nested data structures in custom_data" do
77
+ user = Intercom::User.new()
78
+ proc { user.custom_data["thing"] = [1] }.must_raise ArgumentError
79
+ proc { user.custom_data["thing"] = {1 => 2} }.must_raise ArgumentError
80
+
81
+ user = Intercom::User.from_api(test_user)
82
+ proc { user.custom_data["thing"] = [1] }.must_raise ArgumentError
83
+ end
84
+
85
+ it "fetches a user" do
86
+ Intercom.expects(:get).with("users", {"email" => "bo@example.com"}).returns(test_user)
87
+ user = Intercom::User.find("email" => "bo@example.com")
88
+ user.email.must_equal "bo@example.com"
89
+ user.name.must_equal "Joe Schmoe"
90
+ user.session_count.must_equal 123
91
+ end
92
+
93
+ it "saves a user" do
94
+ user = Intercom::User.new("email" => "jo@example.com", :user_id => "i-1224242")
95
+ Intercom.expects(:post).with("users", {"email" => "jo@example.com", "user_id" => "i-1224242"}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
96
+ user.save
97
+ end
98
+
99
+ it "can use User.create for convenience" do
100
+ Intercom.expects(:post).with("users", {"email" => "jo@example.com", "user_id" => "i-1224242"}).returns({"email" => "jo@example.com", "user_id" => "i-1224242"})
101
+ user = Intercom::User.create("email" => "jo@example.com", :user_id => "i-1224242")
102
+ user.email.must_equal "jo@example.com"
103
+ end
104
+
105
+ it "updates the @user with attributes as set by the server" do
106
+ Intercom.expects(:post).with("users", {"email" => "jo@example.com", "user_id" => "i-1224242"}).returns({"email" => "jo@example.com", "user_id" => "i-1224242", "session_count" => 4})
107
+ user = Intercom::User.create("email" => "jo@example.com", :user_id => "i-1224242")
108
+ user.session_count.must_equal 4
109
+ end
110
+
111
+ it "raises argument error when trying to set a read only attribute" do
112
+ read_only_attributes = %w(relationship_score last_impression_at session_count)
113
+ read_only_attributes.each do |read_only|
114
+ proc { Intercom::User.create("email" => "jo@example.com", read_only => "some value") }.must_raise NoMethodError
115
+ user = Intercom::User.new
116
+ user.public_methods.include?("#{read_only}=").must_equal false
117
+ end
118
+ end
119
+
120
+ it "sets/gets rw keys" do
121
+ 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}
122
+ user = Intercom::User.new(params)
123
+ user.to_hash.keys.sort.must_equal params.keys.map(&:to_s).sort
124
+ params.keys.each do | key|
125
+ user.send(key).to_s.must_equal params[key].to_s
126
+ end
127
+ end
128
+
129
+ it "will allow extra attributes in response from api" do
130
+ user = Intercom::User.send(:from_api, {"new_param" => "some value"})
131
+ user.new_param.must_equal "some value"
132
+ end
133
+ end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ describe Intercom do
4
+ it "has a version number" do
5
+ Intercom::VERSION.must_equal "0.0.2"
6
+ end
7
+
8
+ describe "API" do
9
+ before do
10
+ Intercom.app_id = "abc123"
11
+ Intercom.secret_key = "super-secret-key"
12
+ end
13
+
14
+ it "raises ArgumentError if no app_id or secret_key specified" do
15
+ Intercom.app_id = nil
16
+ Intercom.secret_key = nil
17
+ proc { Intercom.url_for_path("something") }.must_raise ArgumentError, "You must set both Intercom.app_id and Intercom.secret_key to use this client. See https://github.com/intercom/intercom-ruby for usage examples."
18
+ end
19
+
20
+ it "defaults to https to api.intercom.io" do
21
+ Intercom.url_for_path("some/resource/path").must_equal "https://abc123:super-secret-key@api.intercom.io/v1/some/resource/path"
22
+ end
23
+
24
+ it "raises ResourceNotFound if get a 404" do
25
+
26
+ end
27
+
28
+ describe "overriding protocol/hostname" do
29
+ before do
30
+ @protocol = Intercom.protocol
31
+ @hostname = Intercom.hostname
32
+ end
33
+
34
+ after do
35
+ Intercom.protocol = @protocol
36
+ Intercom.hostname = @hostname
37
+ end
38
+
39
+ it "allows overriding of the endpoint and protocol" do
40
+ Intercom.protocol = "http"
41
+ Intercom.hostname = "localhost:3000"
42
+ Intercom.url_for_path("some/resource/path").must_equal "http://abc123:super-secret-key@localhost:3000/v1/some/resource/path"
43
+ end
44
+ end
45
+ end
46
+
47
+ it "checks for email or user id" do
48
+ proc { Intercom.require_email_or_user_id("else") }.must_raise ArgumentError, "Expected params Hash, got String"
49
+ proc { Intercom.require_email_or_user_id(:something => "else") }.must_raise ArgumentError, "Either email or user_id must be specified"
50
+ proc { Intercom.get("users", :something => "else") }.must_raise ArgumentError, "Either email or user_id must be specified"
51
+ proc { Intercom.put("users", :something => "else") }.must_raise ArgumentError, "Either email or user_id must be specified"
52
+ proc { Intercom.post("users", :something => "else") }.must_raise ArgumentError, "Either email or user_id must be specified"
53
+ Intercom.require_email_or_user_id(:email => "bob@example.com", :something => "else")
54
+ Intercom.require_email_or_user_id("email" => "bob@example.com", :something => "else")
55
+ Intercom.require_email_or_user_id(:user_id => "123")
56
+ end
57
+ end
@@ -0,0 +1,80 @@
1
+ require 'intercom'
2
+ require 'minitest/autorun'
3
+ require 'mocha'
4
+
5
+ def test_user
6
+ {
7
+ :user_id => 'id-from-customers-app',
8
+ :email => "bo@example.com",
9
+ :name => "Joe Schmoe",
10
+ :created_at => 1323422442,
11
+ :last_seen_ip => "1.2.3.4",
12
+ :last_seen_user_agent => "Mozilla blah blah ie6",
13
+ :custom_data => {"a" => "b", "b" => 2},
14
+ :relationship_score => 90,
15
+ :session_count => 123,
16
+ :last_impression_at => 1323422442,
17
+ :social_profiles => [
18
+ {"type" => "twitter", "url" => "http://twitter.com/abc", "username" => "abc"},
19
+ {"type" => "twitter", "username" => "abc2", "url" => "http://twitter.com/abc2"},
20
+ {"type" => "facebook", "url" => "http://facebook.com/abc", "username" => "abc", "id" => "1234242"},
21
+ {"type" => "quora", "url" => "http://facebook.com/abc", "username" => "abc", "id" => "1234242"}
22
+ ],
23
+ :location_data => {
24
+ "country_code" => "IRL"
25
+ }
26
+ }
27
+ end
28
+
29
+ def test_messages
30
+ [test_message, test_message]
31
+ end
32
+
33
+ def test_message
34
+ {
35
+ "created_at" => 1329837506,
36
+ "updated_at" => 1329664706,
37
+ "read" => true,
38
+ "created_by_user" => true,
39
+ "thread_id" => 5591,
40
+ "messages" => [
41
+ {
42
+ "created_at" => 1329837506,
43
+ "html" => "<p>Hey Intercom, What is up?</p>\n",
44
+ "from" => {
45
+ "email" => "bob@example.com",
46
+ "name" => "Bob",
47
+ "user_id" => "123",
48
+ "is_admin" => false
49
+ }
50
+ },
51
+ {
52
+ "created_at" => 1329664706,
53
+ "rendered_body" => "<p>Not much, you?</p>\n",
54
+ "from" => {
55
+ "name" => "Super Duper Admin",
56
+ "avatar_path_50" => "https//s3.amazonaws.com/intercom-prod/app/public/system/avatars/1454/medium/intercom-ben-avatar.jpg?1326725052",
57
+ "is_admin" => true
58
+ }
59
+ },
60
+ {
61
+ "created_at" => 1329664806,
62
+ "rendered_body" => "<p>Not much either :(</p>\n",
63
+ "from" => {
64
+ "email" => "bob@example.com",
65
+ "name" => "Bob",
66
+ "user_id" => "123",
67
+ "is_admin" => false
68
+ }
69
+ }
70
+ ]
71
+ }
72
+ end
73
+
74
+ def capture_exception(&block)
75
+ begin
76
+ block.call
77
+ rescue => e
78
+ return e
79
+ end
80
+ end