intercom 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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