lita-totems 0.1.0 → 0.2.0

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