twitter_ebooks_poll 3.2.0

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.
data/spec/bot_spec.rb ADDED
@@ -0,0 +1,216 @@
1
+ require 'spec_helper'
2
+ require 'memory_profiler'
3
+ require 'tempfile'
4
+ require 'timecop'
5
+
6
+ class TestBot < Ebooks::Bot
7
+ attr_accessor :twitter
8
+
9
+ def configure
10
+ end
11
+
12
+ def on_message(dm)
13
+ reply dm, "echo: #{dm.text}"
14
+ end
15
+
16
+ def on_mention(tweet)
17
+ reply tweet, "echo: #{meta(tweet).mentionless}"
18
+ end
19
+
20
+ def on_timeline(tweet)
21
+ reply tweet, "fine tweet good sir"
22
+ end
23
+ end
24
+
25
+ module Ebooks::Test
26
+ # Generates a random twitter id
27
+ # Or a non-random one, given a string.
28
+ def twitter_id(seed = nil)
29
+ if seed.nil?
30
+ (rand*10**18).to_i
31
+ else
32
+ id = 1
33
+ seed.downcase.each_byte do |byte|
34
+ id *= byte/10
35
+ end
36
+ id
37
+ end
38
+ end
39
+
40
+ # Creates a mock direct message
41
+ # @param username User sending the DM
42
+ # @param text DM content
43
+ def mock_dm(username, text)
44
+ Twitter::DirectMessage.new(id: twitter_id,
45
+ sender: { id: twitter_id(username), screen_name: username},
46
+ text: text)
47
+ end
48
+
49
+ # Creates a mock tweet
50
+ # @param username User sending the tweet
51
+ # @param text Tweet content
52
+ def mock_tweet(username, text, extra={})
53
+ mentions = text.split.find_all { |x| x.start_with?('@') }
54
+ tweet = Twitter::Tweet.new({
55
+ id: twitter_id,
56
+ in_reply_to_status_id: 'mock-link',
57
+ user: { id: twitter_id(username), screen_name: username },
58
+ text: text,
59
+ created_at: Time.now.to_s,
60
+ entities: {
61
+ user_mentions: mentions.map { |m|
62
+ { screen_name: m.split('@')[1],
63
+ indices: [text.index(m), text.index(m)+m.length] }
64
+ }
65
+ }
66
+ }.merge!(extra))
67
+ tweet
68
+ end
69
+
70
+ # Creates a mock user
71
+ def mock_user(username)
72
+ Twitter::User.new(id: twitter_id(username), screen_name: username)
73
+ end
74
+
75
+ def twitter_spy(bot)
76
+ twitter = spy("twitter")
77
+ allow(twitter).to receive(:update).and_return(mock_tweet(bot.username, "test tweet"))
78
+ allow(twitter).to receive(:user).with(no_args).and_return(mock_user(bot.username))
79
+ twitter
80
+ end
81
+
82
+ def simulate(bot, &b)
83
+ bot.twitter = twitter_spy(bot)
84
+ bot.update_myself # Usually called in prepare
85
+ b.call
86
+ end
87
+
88
+ def expect_direct_message(bot, content)
89
+ expect(bot.twitter).to have_received(:create_direct_message).with(anything(), content, {})
90
+ bot.twitter = twitter_spy(bot)
91
+ end
92
+
93
+ def expect_tweet(bot, content)
94
+ expect(bot.twitter).to have_received(:update).with(content, anything())
95
+ bot.twitter = twitter_spy(bot)
96
+ end
97
+ end
98
+
99
+
100
+ describe Ebooks::Bot do
101
+ include Ebooks::Test
102
+ let(:bot) { TestBot.new('Test_Ebooks') }
103
+
104
+ before { Timecop.freeze }
105
+ after { Timecop.return }
106
+
107
+ it "responds to dms" do
108
+ simulate(bot) do
109
+ bot.receive_event(mock_dm("m1sp", "this is a dm"))
110
+ expect_direct_message(bot, "echo: this is a dm")
111
+ end
112
+ end
113
+
114
+ it "ignores its own dms" do
115
+ simulate(bot) do
116
+ expect(bot).to_not receive(:on_message)
117
+ bot.receive_event(mock_dm("Test_Ebooks", "why am I talking to myself"))
118
+ end
119
+ end
120
+
121
+ it "responds to mentions" do
122
+ simulate(bot) do
123
+ bot.receive_event(mock_tweet("m1sp", "@test_ebooks this is a mention"))
124
+ expect_tweet(bot, "@m1sp echo: this is a mention")
125
+ end
126
+ end
127
+
128
+ it "ignores its own mentions" do
129
+ simulate(bot) do
130
+ expect(bot).to_not receive(:on_mention)
131
+ expect(bot).to_not receive(:on_timeline)
132
+ bot.receive_event(mock_tweet("Test_Ebooks", "@m1sp i think that @test_ebooks is best bot"))
133
+ end
134
+ end
135
+
136
+ it "responds to timeline tweets" do
137
+ simulate(bot) do
138
+ bot.receive_event(mock_tweet("m1sp", "some excellent tweet"))
139
+ expect_tweet(bot, "@m1sp fine tweet good sir")
140
+ end
141
+ end
142
+
143
+ it "ignores its own timeline tweets" do
144
+ simulate(bot) do
145
+ expect(bot).to_not receive(:on_timeline)
146
+ bot.receive_event(mock_tweet("Test_Ebooks", "pudding is cute"))
147
+ end
148
+ end
149
+
150
+ it "links tweets to conversations correctly" do
151
+ tweet1 = mock_tweet("m1sp", "tweet 1", id: 1, in_reply_to_status_id: nil)
152
+
153
+ tweet2 = mock_tweet("m1sp", "tweet 2", id: 2, in_reply_to_status_id: 1)
154
+
155
+ tweet3 = mock_tweet("m1sp", "tweet 3", id: 3, in_reply_to_status_id: nil)
156
+
157
+ bot.conversation(tweet1).add(tweet1)
158
+ expect(bot.conversation(tweet2)).to eq(bot.conversation(tweet1))
159
+
160
+ bot.conversation(tweet2).add(tweet2)
161
+ expect(bot.conversation(tweet3)).to_not eq(bot.conversation(tweet2))
162
+ end
163
+
164
+ it "stops mentioning people after a certain limit" do
165
+ simulate(bot) do
166
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 1"))
167
+ expect_tweet(bot, "@spammer @m1sp echo: 1")
168
+
169
+ Timecop.travel(Time.now + 60)
170
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 2"))
171
+ expect_tweet(bot, "@spammer @m1sp echo: 2")
172
+
173
+ Timecop.travel(Time.now + 60)
174
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 3"))
175
+ expect_tweet(bot, "@spammer echo: 3")
176
+ end
177
+ end
178
+
179
+ it "doesn't stop mentioning them if they reply" do
180
+ simulate(bot) do
181
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 4"))
182
+ expect_tweet(bot, "@spammer @m1sp echo: 4")
183
+
184
+ Timecop.travel(Time.now + 60)
185
+ bot.receive_event(mock_tweet("m1sp", "@spammer @test_ebooks 5"))
186
+ expect_tweet(bot, "@m1sp @spammer echo: 5")
187
+
188
+ Timecop.travel(Time.now + 60)
189
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 6"))
190
+ expect_tweet(bot, "@spammer @m1sp echo: 6")
191
+ end
192
+ end
193
+
194
+ it "doesn't get into infinite bot conversations" do
195
+ simulate(bot) do
196
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 7"))
197
+ expect_tweet(bot, "@spammer @m1sp echo: 7")
198
+
199
+ Timecop.travel(Time.now + 2)
200
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 8"))
201
+ expect_tweet(bot, "@spammer @m1sp echo: 8")
202
+
203
+ Timecop.travel(Time.now + 2)
204
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 9"))
205
+ expect(bot.twitter).to_not have_received(:update)
206
+ end
207
+ end
208
+
209
+ it "blocks blacklisted users on contact" do
210
+ simulate(bot) do
211
+ bot.blacklist = ["spammer"]
212
+ bot.receive_event(mock_tweet("spammer", "@test_ebooks @m1sp 7"))
213
+ expect(bot.twitter).to have_received(:block).with("spammer")
214
+ end
215
+ end
216
+ end