lita-totems 0.1.0 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52a873b89b3b0fcda3f1ac5cb94df40319ce0898
4
- data.tar.gz: 9be24d8f06768443fe0cab96f3fa80cd71b3d055
3
+ metadata.gz: fcebd655b6abfd2ae0fffb0e2477455a847b24fd
4
+ data.tar.gz: 078b012853bfc626e605eb8d7f20c128b99e9187
5
5
  SHA512:
6
- metadata.gz: e36de592b355f98f4ca21785829f165d0eb22ec3b4532d32ba8b3c54246014e43c18af94f550018a690378cafee197bf4aac21a2063f4a527f5dc6f684b7b39c
7
- data.tar.gz: d56dba1969ac6a4369cfbbc35d76a1a353ddd9d2f70052f6aef263fc44dac33ec3774ecec0f88355c95f04b38f5c03e7a4f9107aef3cb4b25f05fdcbf5da0cc5
6
+ metadata.gz: 53da90a7de19a6d7143b77dc7ab7716cb6749b8acc130210b4f86f3a3463b0541637b5c4d43a459b02539a890be51f2308825774bf8a004dd72f909404beba1f
7
+ data.tar.gz: 2d4c22bc113044b5e75d4a4df7f2b97681a44c737d032dd7f383cc0d5cc6c8a73e48ca5cc34a7c52cd129ece6d430afabfee9e04ef42360225745d72444cbabb
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .ruby-version
1
2
  *.gem
2
3
  *.rbc
3
4
  .bundle
@@ -1,6 +1,5 @@
1
- require "lita"
2
- require 'active_support/core_ext/integer/inflections'
3
- require 'active_support/core_ext/object/blank'
1
+ require 'lita'
2
+ require 'chronic_duration'
4
3
  require 'redis-semaphore'
5
4
 
6
5
  module Lita
@@ -56,11 +55,11 @@ module Lita
56
55
  )?
57
56
  $
58
57
  }x,
59
- :info,
60
- help: {
61
- 'totems info' => "Shows info of all totems queues",
62
- 'totems info TOTEM' => 'Shows info of just one totem'
63
- })
58
+ :info,
59
+ help: {
60
+ 'totems info' => "Shows info of all totems queues",
61
+ 'totems info TOTEM' => 'Shows info of just one totem'
62
+ })
64
63
 
65
64
  def destroy(response)
66
65
  totem = response.match_data[:totem]
@@ -70,6 +69,7 @@ module Lita
70
69
  redis.srem("totems", totem)
71
70
  owning_user_id = redis.get("totem/#{totem}/owning_user_id")
72
71
  redis.srem("user/#{owning_user_id}/totems", totem) if owning_user_id
72
+ redis.del("totem/#{totem}/waiting_since")
73
73
  response.reply(%{Destroyed totem "#{totem}".})
74
74
  else
75
75
  response.reply(%{Error: totem "#{totem}" doesn't exist.})
@@ -98,45 +98,65 @@ module Lita
98
98
 
99
99
  user_id = response.user.id
100
100
 
101
+ if queued_by_user(user_id).include?(totem)
102
+ response.reply %{Error: you are already in the queue for "#{totem}".}
103
+ return
104
+ end
105
+
106
+ if redis.smembers("user/#{user_id}/totems").include?(totem)
107
+ response.reply %{Error: you already have the totem "#{totem}".}
108
+ return
109
+ end
110
+
101
111
  token_acquired = false
102
112
  queue_size = nil
103
113
  Redis::Semaphore.new("totem/#{totem}", redis: redis).lock do
104
- if redis.llen("totem/#{totem}/list") == 0 && redis.get("totem/#{totem}/owning_user_id").blank?
114
+ if redis.llen("totem/#{totem}/list") == 0 && redis.get("totem/#{totem}/owning_user_id").nil?
105
115
  # take it:
106
116
  token_acquired = true
107
117
  redis.set("totem/#{totem}/owning_user_id", user_id)
118
+ redis.hset("totem/#{totem}/waiting_since", user_id, Time.now.to_i)
108
119
  else
109
120
  # queue:
110
- queue_size = redis.lpush("totem/#{totem}/list", user_id)
121
+ queue_size = redis.rpush("totem/#{totem}/list", user_id)
122
+ redis.hset("totem/#{totem}/waiting_since", user_id, Time.now.to_i)
111
123
  end
112
124
  end
113
125
 
114
126
  if token_acquired
127
+ # TODO don't readd to totems you are already waiting for!
115
128
  redis.sadd("user/#{user_id}/totems", totem)
116
129
  response.reply(%{#{response.user.name}, you now have totem "#{totem}".})
117
130
  else
118
- response.reply(%{#{response.user.name}, you are #{queue_size.ordinalize} in line for totem "#{totem}".})
131
+ response.reply(%{#{response.user.name}, you are \##{queue_size} in line for totem "#{totem}".})
119
132
  end
120
133
 
121
134
  end
122
135
 
123
136
  def yield(response)
124
- user_id = response.user.id
125
- totems_owned_by_user = redis.smembers("user/#{user_id}/totems")
126
- if totems_owned_by_user.empty?
137
+ user_id = response.user.id
138
+ totems_owned_by_user = redis.smembers("user/#{user_id}/totems")
139
+ totems_queued_by_user = queued_by_user(user_id)
140
+ if totems_owned_by_user.empty? && totems_queued_by_user.empty?
127
141
  response.reply "Error: You do not have any totems to yield."
128
- elsif totems_owned_by_user.size == 1
142
+ elsif totems_owned_by_user.size == 1 && !response.match_data[:totem] && totems_queued_by_user.empty?
129
143
  yield_totem(totems_owned_by_user[0], user_id, response)
130
- else # totems count > 1
144
+ else
131
145
  totem_specified = response.match_data[:totem]
146
+ # if they don't specify and are only queued for a single totem, yield that one
147
+ totem_specified = totems_queued_by_user.first if !totem_specified && totems_queued_by_user.size == 1 && totems_owned_by_user.empty?
132
148
  if totem_specified
133
149
  if totems_owned_by_user.include?(totem_specified)
134
150
  yield_totem(totem_specified, user_id, response)
151
+ elsif totems_queued_by_user.include?(totem_specified)
152
+ redis.lrem("totem/#{totem_specified}/list", 0, user_id)
153
+ redis.hdel("totem/#{totem_specified}/waiting_since", user_id)
154
+ response.reply("You are no longer in line for the \"#{totem_specified}\" totem.")
135
155
  else
136
- response.reply %{Error: You don't own the "#{totem_specified}" totem.}
156
+ response.reply %{Error: You don't own and aren't waiting for the "#{totem_specified}" totem.}
137
157
  end
138
158
  else
139
- response.reply "You must specify a totem to yield. Totems you own: #{totems_owned_by_user.sort}"
159
+ response.reply "You must specify a totem to yield. Totems you own: #{totems_owned_by_user.sort}. Totems you are in line for: #{totems_queued_by_user.sort}."
140
160
  end
141
161
  end
142
162
  end
@@ -155,57 +175,85 @@ module Lita
155
175
  end
156
176
 
157
177
  redis.srem("user/#{past_owning_user_id}/totems", totem)
158
- robot.send_messages(User.new(past_owning_user_id), %{You have been kicked from totem "#{totem}".})
178
+ redis.hdel("totem/#{totem}/waiting_since", past_owning_user_id)
179
+ robot.send_messages(Lita::Source.new(user: Lita::User.find_by_id(past_owning_user_id)), %{You have been kicked from totem "#{totem}".})
159
180
  next_user_id = redis.lpop("totem/#{totem}/list")
160
- redis.set("totem/#{totem}/owning_user_id", next_user_id)
161
181
  if next_user_id
182
+ redis.set("totem/#{totem}/owning_user_id", next_user_id)
162
183
  redis.sadd("user/#{next_user_id}/totems", totem)
163
- robot.send_messages(User.new(next_user_id), %{You are now in possession of totem "#{totem}".})
184
+ redis.hset("totem/#{totem}/waiting_since", next_user_id, Time.now.to_i)
185
+ robot.send_messages(Lita::Source.new(user: Lita::User.find_by_id(next_user_id)), %{You are now in possession of totem "#{totem}".})
186
+ else
187
+ redis.del("totem/#{totem}/owning_user_id")
164
188
  end
165
189
 
166
190
  end
167
191
 
168
192
  def info(response)
169
193
  totem_param = response.match_data[:totem]
170
- resp = if totem_param.present?
171
- list_users_print(totem_param)
172
- else
173
- r = "Totems:\n"
174
- redis.smembers("totems").each do |totem|
175
- r += "- #{totem}\n"
176
- r += list_users_print(totem, ' ')
177
- end
178
- r
179
- end
194
+ resp = unless totem_param.nil? || totem_param.empty?
195
+ list_users_print(totem_param)
196
+ else
197
+ users_cache = new_users_cache
198
+ r = "Totems:\n"
199
+ redis.smembers("totems").each do |totem|
200
+ r += "- #{totem}\n"
201
+ r += list_users_print(totem, ' ', users_cache)
202
+ end
203
+ r
204
+ end
180
205
  response.reply resp
181
206
  end
182
207
 
183
208
  private
184
- def list_users_print(totem, prefix='')
209
+ def new_users_cache
210
+ Hash.new { |h, id| h[id] = Lita::User.find_by_id(id) }
211
+ end
212
+
213
+ def list_users_print(totem, prefix='', users_cache=new_users_cache)
185
214
  str = ''
186
215
  first_id = redis.get("totem/#{totem}/owning_user_id")
187
216
  if first_id
188
- str += "#{prefix}1. User id #{first_id}\n"
217
+ waiting_since_hash = redis.hgetall("totem/#{totem}/waiting_since")
218
+ str += "#{prefix}1. #{users_cache[first_id].name} (held for #{waiting_duration(waiting_since_hash[first_id])})\n"
189
219
  rest = redis.lrange("totem/#{totem}/list", 0, -1)
190
220
  rest.each_with_index do |user_id, index|
191
- str += "#{prefix}#{index+2}. User id #{user_id}\n"
221
+ str += "#{prefix}#{index+2}. #{users_cache[user_id].name} (waiting for #{waiting_duration(waiting_since_hash[user_id])})\n"
192
222
  end
193
223
  end
194
224
  str
195
225
  end
196
226
 
227
+ def waiting_duration(time)
228
+ ChronicDuration.output(Time.now.to_i - time.to_i, format: :short) || "0s"
229
+ end
230
+
197
231
  def yield_totem(totem, user_id, response)
198
232
  redis.srem("user/#{user_id}/totems", totem)
233
+ redis.hdel("totem/#{totem}/waiting_since", user_id)
199
234
  next_user_id = redis.lpop("totem/#{totem}/list")
200
235
  if next_user_id
236
+ redis.set("totem/#{totem}/owning_user_id", next_user_id)
201
237
  redis.sadd("user/#{next_user_id}/totems", totem)
202
- robot.send_messages(User.new(next_user_id), %{You are now in possession of totem "#{totem}."})
203
- response.reply "You have yielded the totem to #{next_user_id}."
238
+ redis.hset("totem/#{totem}/waiting_since", next_user_id, Time.now.to_i)
239
+ next_user = Lita::User.find_by_id(next_user_id)
240
+ robot.send_messages(Lita::Source.new(user: next_user), %{You are now in possession of totem "#{totem}."})
241
+ response.reply "You have yielded the totem to #{next_user.name}."
204
242
  else
243
+ redis.del("totem/#{totem}/owning_user_id")
205
244
  response.reply %{You have yielded the "#{totem}" totem.}
206
245
  end
207
- redis.set("totem/#{totem}/owning_user_id", next_user_id)
208
246
  end
247
+
248
+ def queued_by_user(user_id)
249
+ redis.smembers("totems").select do |totem|
250
+ # there's no easy way to check membership in a list in redis
251
+ # right now let's iterate through the list, but to make this
252
+ # more performant we could convert these lists to sorted sets
253
+ redis.lrange("totem/#{totem}/list", 0, -1).include?(user_id)
254
+ end
255
+ end
256
+
209
257
  end
210
258
 
211
259
  Lita.register_handler(Totems)
data/lita-totems.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-totems"
3
- spec.version = "0.1.0"
4
- spec.authors = ["Charles Finkel"]
5
- spec.email = ["cf@dropbox.com"]
3
+ spec.version = "0.2.0"
4
+ spec.authors = ["Charles Finkel", "Vijay Ramesh"]
5
+ spec.email = ["cf@dropbox.com", "vijay@change.org"]
6
6
  spec.description = %q{Totems handler for Lita)}
7
7
  spec.summary = %q{Adds support to Lita for Totems}
8
8
  spec.homepage = "https://github.com/charleseff/lita-totems"
@@ -13,13 +13,14 @@ Gem::Specification.new do |spec|
13
13
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
14
14
  spec.require_paths = ["lib"]
15
15
 
16
- spec.add_runtime_dependency "lita", "~> 2.4"
17
- spec.add_runtime_dependency "activesupport"
16
+ spec.add_runtime_dependency "lita", ">= 2.4"
17
+ spec.add_runtime_dependency "chronic_duration"
18
18
  spec.add_runtime_dependency "redis-semaphore"
19
19
 
20
20
  spec.add_development_dependency "bundler", "~> 1.3"
21
21
  spec.add_development_dependency "rake"
22
- spec.add_development_dependency "rspec", ">= 2.14"
22
+ spec.add_development_dependency "rspec", ">= 3.0.0.beta1"
23
23
  spec.add_development_dependency "simplecov"
24
+ spec.add_development_dependency "timecop"
24
25
  spec.add_development_dependency "coveralls"
25
26
  end
@@ -97,9 +97,30 @@ describe Lita::Handlers::Totems, lita_handler: true do
97
97
  end
98
98
  it "adds user to the queue" do
99
99
  send_message("totems add chicken", as: carl)
100
- expect(replies.last).to eq('Carl, you are 2nd in line for totem "chicken".')
100
+ expect(replies.last).to eq('Carl, you are #2 in line for totem "chicken".')
101
101
  end
102
102
  end
103
+ context "when the user is already holding the totem" do
104
+ before do
105
+ send_message("totems add chicken", as: carl)
106
+ end
107
+ it "returns an error message" do
108
+ send_message("totems add chicken", as: carl)
109
+ expect(replies.last).to eq('Error: you already have the totem "chicken".')
110
+ end
111
+ end
112
+
113
+ context "when the user is already in line for the totem" do
114
+ before do
115
+ send_message("totems add chicken", as: another_user)
116
+ send_message("totems add chicken", as: carl)
117
+ end
118
+ it "returns an error message" do
119
+ send_message("totems add chicken", as: carl)
120
+ expect(replies.last).to eq('Error: you are already in the queue for "chicken".')
121
+ end
122
+ end
123
+
103
124
  end
104
125
 
105
126
  context "when the totem doesn't exist" do
@@ -107,39 +128,61 @@ describe Lita::Handlers::Totems, lita_handler: true do
107
128
  send_message("totems add chicken", as: carl)
108
129
  expect(replies.last).to eq('Error: there is no totem "chicken".')
109
130
  end
110
-
111
131
  end
112
-
113
132
  end
114
133
 
115
134
  describe "yield" do
116
135
  before do
117
136
  send_message("totems create chicken")
137
+ send_message("totems create duck")
118
138
  end
119
139
 
120
140
  context "when user has one totem" do
121
141
  before do
122
- send_message("totems add chicken", as: carl)
142
+ Timecop.freeze("2014-03-01 11:00:00") do
143
+ send_message("totems add chicken", as: carl)
144
+ end
123
145
  end
124
146
 
125
147
  context "someone else is in line" do
126
148
  before do
127
- send_message("totems add chicken", as: another_user)
149
+ Timecop.freeze("2014-03-01 12:00:00") do
150
+ send_message("totems add chicken", as: another_user)
151
+ send_message("totems add chicken", as: yet_another_user)
152
+ end
128
153
  end
129
154
  it "yields that totem, gives to the next person in line" do
130
155
  expect(robot).to receive(:send_messages) do |target, message|
131
- expect(target.id).to eq(another_user.id)
156
+ expect(target.user.id).to eq(another_user.id)
132
157
  expect(message).to eq(%{You are now in possession of totem "chicken."})
133
158
  end
134
159
  send_message("totems yield", as: carl)
135
160
  # todo: check for message to other user
136
- expect(replies.last).to eq("You have yielded the totem to #{another_user.id}.")
161
+ expect(replies.last).to eq("You have yielded the totem to #{another_user.name}.")
162
+ end
163
+ it "updates the waiting since value for the new holder" do
164
+ Timecop.freeze("2014-03-01 13:00:00") do
165
+ send_message("totems info chicken")
166
+ expect(replies.last).to eq <<-END
167
+ 1. Carl (held for 2h)
168
+ 2. Test User (waiting for 1h)
169
+ 3. person_2 (waiting for 1h)
170
+ END
171
+ send_message("totems yield", as: carl)
172
+ send_message("totems info chicken")
173
+ expect(replies.last).to eq <<-END
174
+ 1. Test User (held for 0s)
175
+ 2. person_2 (waiting for 1h)
176
+ END
177
+ end
137
178
  end
138
179
  end
139
180
  context "nobody else is in line" do
140
- it "yields the totem" do
181
+ it "yields the totem and clears the owning_user_id" do
141
182
  send_message("totems yield", as: carl)
142
183
  expect(replies.last).to eq(%{You have yielded the "chicken" totem.})
184
+ send_message("totems info chicken")
185
+ expect(replies.last).to eq ""
143
186
  end
144
187
  end
145
188
  end
@@ -159,7 +202,7 @@ describe Lita::Handlers::Totems, lita_handler: true do
159
202
  context "user doesn't have that totem" do
160
203
  it "sends error message" do
161
204
  send_message("totems yield duck", as: carl)
162
- expect(replies.last).to eq(%{Error: You don't own the "duck" totem.})
205
+ expect(replies.last).to eq(%{Error: You don't own and aren't waiting for the "duck" totem.})
163
206
  end
164
207
  end
165
208
  context "user has that totem" do
@@ -173,36 +216,149 @@ describe Lita::Handlers::Totems, lita_handler: true do
173
216
  context "when not specifying a totem" do
174
217
  it "sends a message about which totem it can yield" do
175
218
  send_message("totems yield", as: carl)
176
- expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["chicken", "#{other_totem}"]})
219
+ expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["chicken", "#{other_totem}"]. Totems you are in line for: [].})
177
220
  end
178
221
  end
222
+ end
223
+ context "when the user is in line for a single totem" do
224
+ before do
225
+ Timecop.freeze("2014-03-02 13:00:00") do
226
+ send_message("totems add chicken", as: another_user)
227
+ send_message("totems add chicken", as: carl)
228
+ end
229
+ end
230
+ context "when specifying a totem" do
231
+ context "user is not in line for that totem" do
232
+ it "sends error message" do
233
+ send_message("totems yield duck", as: carl)
234
+ expect(replies.last).to eq(%{Error: You don't own and aren't waiting for the "duck" totem.})
235
+ end
236
+ end
237
+ context "user is in line for that totem" do
238
+ it "yields totem and does not update holder" do
239
+ Timecop.freeze("2014-03-02 14:00:00") do
240
+ send_message("totems yield chicken", as: carl)
241
+ expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
242
+ send_message("totems info chicken")
243
+ expect(replies.last).to eq("1. Test User (held for 1h)\n")
244
+ end
245
+ end
246
+ end
247
+ end
248
+ context "when not specifying a totem" do
249
+ it "yields totem and does not update holder" do
250
+ Timecop.freeze("2014-03-02 14:00:00") do
251
+ send_message("totems yield", as: carl)
252
+ expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
253
+ send_message("totems info chicken")
254
+ expect(replies.last).to eq("1. Test User (held for 1h)\n")
255
+ end
256
+ end
257
+ end
258
+ end
179
259
 
260
+ context "when the user is in line for multiple totems" do
261
+ before do
262
+ Timecop.freeze("2014-03-02 13:00:00") do
263
+ send_message("totems add chicken", as: another_user)
264
+ send_message("totems add chicken", as: carl)
265
+ send_message("totems add chicken", as: yet_another_user)
266
+ send_message("totems add duck", as: yet_another_user)
267
+ send_message("totems add duck", as: carl)
268
+ end
269
+ end
270
+ context "when specifying a totem" do
271
+ context "user is in line for that totem" do
272
+ it "yields totem and does not update holder" do
273
+ Timecop.freeze("2014-03-02 14:00:00") do
274
+ send_message("totems yield chicken", as: carl)
275
+ expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
276
+ send_message("totems info chicken")
277
+ expect(replies.last).to eq("1. Test User (held for 1h)\n2. person_2 (waiting for 1h)\n")
278
+ end
279
+ end
280
+ end
281
+ end
282
+ context "when not specifying a totem" do
283
+ it "sends error message" do
284
+ Timecop.freeze("2014-03-02 14:00:00") do
285
+ send_message("totems yield", as: carl)
286
+ expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: []. Totems you are in line for: ["chicken", "duck"].})
287
+ end
288
+ end
289
+ end
180
290
  end
181
291
 
292
+ context "when the user is in line for a totem and has another totem" do
293
+ before do
294
+ Timecop.freeze("2014-03-02 13:00:00") do
295
+ send_message("totems add chicken", as: another_user)
296
+ send_message("totems add chicken", as: carl)
297
+ send_message("totems add chicken", as: yet_another_user)
298
+ send_message("totems add duck", as: carl)
299
+ send_message("totems add duck", as: another_user)
300
+ end
301
+ end
302
+ context "when specifying a totem" do
303
+ context "user is in line for that totem" do
304
+ it "yields totem and does not update holder" do
305
+ Timecop.freeze("2014-03-02 14:00:00") do
306
+ send_message("totems yield chicken", as: carl)
307
+ expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
308
+ send_message("totems info chicken")
309
+ expect(replies.last).to eq("1. Test User (held for 1h)\n2. person_2 (waiting for 1h)\n")
310
+ end
311
+ end
312
+ end
313
+ end
314
+ context "when not specifying a totem" do
315
+ it "sends error message" do
316
+ Timecop.freeze("2014-03-02 14:00:00") do
317
+ send_message("totems yield", as: carl)
318
+ expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["duck"]. Totems you are in line for: ["chicken"].})
319
+ end
320
+ end
321
+ end
322
+ end
182
323
  end
183
324
 
325
+
326
+
184
327
  describe "kick" do
185
328
  before do
186
329
  send_message("totems create chicken")
187
330
  end
188
- context "there is a user owning the totem" do
331
+ context "there is a user owning the totem and somebody else waiting for it" do
189
332
  before do
190
333
  send_message("totems add chicken", as: another_user)
191
334
  send_message("totems add chicken", as: carl)
192
335
  end
193
336
  it "should notify that user that she has been kicked" do
194
337
  expect(robot).to receive(:send_messages) do |target, message|
195
- expect(target.id).to eq(another_user.id)
338
+ expect(target.user.id).to eq(another_user.id)
196
339
  expect(message).to eq(%{You have been kicked from totem "chicken".})
197
340
  end
198
341
  send_message("totems kick chicken")
199
-
200
342
  end
201
343
  it "should notify next user in line that she now has the totem" do
202
344
  send_message("totems kick chicken")
203
345
  expect(replies.last).to eq(%{You are now in possession of totem "chicken".})
204
346
  end
347
+ end
205
348
 
349
+ context "there is a user owning the totem" do
350
+ before do
351
+ send_message("totems add chicken", as: carl)
352
+ end
353
+ it "should notify that user that she has been kicked and clear the owning_user_id" do
354
+ expect(robot).to receive(:send_messages) do |target, message|
355
+ expect(target.user.id).to eq(carl.id)
356
+ expect(message).to eq(%{You have been kicked from totem "chicken".})
357
+ end
358
+ send_message("totems kick chicken")
359
+ send_message("totems info chicken")
360
+ expect(replies.last).to eq ""
361
+ end
206
362
  end
207
363
 
208
364
  context "nobody owns that totem" do
@@ -215,42 +371,49 @@ describe Lita::Handlers::Totems, lita_handler: true do
215
371
 
216
372
  describe "info" do
217
373
  before do
218
- send_message("totems create chicken")
219
- send_message("totems create duck")
220
- send_message("totems create ball")
221
- send_message("totems add chicken", as: carl)
222
- send_message("totems add chicken", as: another_user)
223
- send_message("totems add duck", as: yet_another_user)
224
- send_message("totems add duck", as: carl)
225
-
374
+ Timecop.freeze("2014-03-01 12:00:00") do
375
+ send_message("totems create chicken")
376
+ send_message("totems create duck")
377
+ send_message("totems create ball")
378
+ send_message("totems add chicken", as: carl)
379
+ send_message("totems add chicken", as: another_user)
380
+ send_message("totems add chicken", as: yet_another_user)
381
+ send_message("totems add duck", as: yet_another_user)
382
+ send_message("totems add duck", as: carl)
383
+ end
226
384
  end
227
385
  context "totem is passed" do
228
386
  it "shows info for just that totem" do
229
- send_message("totems info chicken")
230
- expect(replies.last).to eq <<-END
231
- 1. User id #{carl.id}
232
- 2. User id #{another_user.id}
233
- END
234
-
387
+ Timecop.freeze("2014-03-01 13:00:00") do
388
+ send_message("totems info chicken")
389
+ expect(replies.last).to eq <<-END
390
+ 1. Carl (held for 1h)
391
+ 2. Test User (waiting for 1h)
392
+ 3. person_2 (waiting for 1h)
393
+ END
394
+ end
235
395
  end
236
396
  end
237
397
 
238
398
  context "totem isn't passed" do
239
399
  it "shows info for all totems" do
240
- send_message("totems info")
241
- expect(replies.last).to include <<-END
400
+ Timecop.freeze("2014-03-02 13:00:00") do
401
+ send_message("totems info")
402
+ expect(replies.last).to include <<-END
242
403
  - chicken
243
- 1. User id #{carl.id}
244
- 2. User id #{another_user.id}
245
- END
246
- expect(replies.last).to include <<-END
404
+ 1. Carl (held for 1d 1h)
405
+ 2. Test User (waiting for 1d 1h)
406
+ 3. person_2 (waiting for 1d 1h)
407
+ END
408
+ expect(replies.last).to include <<-END
247
409
  - duck
248
- 1. User id #{yet_another_user.id}
249
- 2. User id #{carl.id}
250
- END
251
- expect(replies.last).to include <<-END
410
+ 1. person_2 (held for 1d 1h)
411
+ 2. Carl (waiting for 1d 1h)
412
+ END
413
+ expect(replies.last).to include <<-END
252
414
  - ball
253
- END
415
+ END
416
+ end
254
417
  end
255
418
  end
256
419
 
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "simplecov"
2
+ require 'timecop'
2
3
  require "coveralls"
3
4
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
4
5
  SimpleCov::Formatter::HTMLFormatter,
metadata CHANGED
@@ -1,136 +1,152 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-totems
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Finkel
8
+ - Vijay Ramesh
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-09-10 00:00:00.000000000 Z
12
+ date: 2014-03-07 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: lita
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
- - - ~>
18
+ - - ">="
18
19
  - !ruby/object:Gem::Version
19
20
  version: '2.4'
20
21
  type: :runtime
21
22
  prerelease: false
22
23
  version_requirements: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ~>
25
+ - - ">="
25
26
  - !ruby/object:Gem::Version
26
27
  version: '2.4'
27
28
  - !ruby/object:Gem::Dependency
28
- name: activesupport
29
+ name: chronic_duration
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - '>='
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
34
  version: '0'
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - '>='
39
+ - - ">="
39
40
  - !ruby/object:Gem::Version
40
41
  version: '0'
41
42
  - !ruby/object:Gem::Dependency
42
43
  name: redis-semaphore
43
44
  requirement: !ruby/object:Gem::Requirement
44
45
  requirements:
45
- - - '>='
46
+ - - ">="
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
48
49
  type: :runtime
49
50
  prerelease: false
50
51
  version_requirements: !ruby/object:Gem::Requirement
51
52
  requirements:
52
- - - '>='
53
+ - - ">="
53
54
  - !ruby/object:Gem::Version
54
55
  version: '0'
55
56
  - !ruby/object:Gem::Dependency
56
57
  name: bundler
57
58
  requirement: !ruby/object:Gem::Requirement
58
59
  requirements:
59
- - - ~>
60
+ - - "~>"
60
61
  - !ruby/object:Gem::Version
61
62
  version: '1.3'
62
63
  type: :development
63
64
  prerelease: false
64
65
  version_requirements: !ruby/object:Gem::Requirement
65
66
  requirements:
66
- - - ~>
67
+ - - "~>"
67
68
  - !ruby/object:Gem::Version
68
69
  version: '1.3'
69
70
  - !ruby/object:Gem::Dependency
70
71
  name: rake
71
72
  requirement: !ruby/object:Gem::Requirement
72
73
  requirements:
73
- - - '>='
74
+ - - ">="
74
75
  - !ruby/object:Gem::Version
75
76
  version: '0'
76
77
  type: :development
77
78
  prerelease: false
78
79
  version_requirements: !ruby/object:Gem::Requirement
79
80
  requirements:
80
- - - '>='
81
+ - - ">="
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0'
83
84
  - !ruby/object:Gem::Dependency
84
85
  name: rspec
85
86
  requirement: !ruby/object:Gem::Requirement
86
87
  requirements:
87
- - - '>='
88
+ - - ">="
88
89
  - !ruby/object:Gem::Version
89
- version: '2.14'
90
+ version: 3.0.0.beta1
90
91
  type: :development
91
92
  prerelease: false
92
93
  version_requirements: !ruby/object:Gem::Requirement
93
94
  requirements:
94
- - - '>='
95
+ - - ">="
95
96
  - !ruby/object:Gem::Version
96
- version: '2.14'
97
+ version: 3.0.0.beta1
97
98
  - !ruby/object:Gem::Dependency
98
99
  name: simplecov
99
100
  requirement: !ruby/object:Gem::Requirement
100
101
  requirements:
101
- - - '>='
102
+ - - ">="
102
103
  - !ruby/object:Gem::Version
103
104
  version: '0'
104
105
  type: :development
105
106
  prerelease: false
106
107
  version_requirements: !ruby/object:Gem::Requirement
107
108
  requirements:
108
- - - '>='
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: timecop
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
109
124
  - !ruby/object:Gem::Version
110
125
  version: '0'
111
126
  - !ruby/object:Gem::Dependency
112
127
  name: coveralls
113
128
  requirement: !ruby/object:Gem::Requirement
114
129
  requirements:
115
- - - '>='
130
+ - - ">="
116
131
  - !ruby/object:Gem::Version
117
132
  version: '0'
118
133
  type: :development
119
134
  prerelease: false
120
135
  version_requirements: !ruby/object:Gem::Requirement
121
136
  requirements:
122
- - - '>='
137
+ - - ">="
123
138
  - !ruby/object:Gem::Version
124
139
  version: '0'
125
140
  description: Totems handler for Lita)
126
141
  email:
127
142
  - cf@dropbox.com
143
+ - vijay@change.org
128
144
  executables: []
129
145
  extensions: []
130
146
  extra_rdoc_files: []
131
147
  files:
132
- - .gitignore
133
- - .travis.yml
148
+ - ".gitignore"
149
+ - ".travis.yml"
134
150
  - Gemfile
135
151
  - LICENSE
136
152
  - README.md
@@ -150,17 +166,17 @@ require_paths:
150
166
  - lib
151
167
  required_ruby_version: !ruby/object:Gem::Requirement
152
168
  requirements:
153
- - - '>='
169
+ - - ">="
154
170
  - !ruby/object:Gem::Version
155
171
  version: '0'
156
172
  required_rubygems_version: !ruby/object:Gem::Requirement
157
173
  requirements:
158
- - - '>='
174
+ - - ">="
159
175
  - !ruby/object:Gem::Version
160
176
  version: '0'
161
177
  requirements: []
162
178
  rubyforge_project:
163
- rubygems_version: 2.0.5
179
+ rubygems_version: 2.2.2
164
180
  signing_key:
165
181
  specification_version: 4
166
182
  summary: Adds support to Lita for Totems