lita-locker 1.0.10 → 1.1.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: 40b2882a9408152241aaa1539bf1c7924e15bcf4
4
- data.tar.gz: 58217f843456a9b13dc82230a79f8f5a99131b78
3
+ metadata.gz: 40e3c6cfb38098e4089ab667b84796cf38dddb98
4
+ data.tar.gz: 01c834e9d945c39cf53fa37c5984384505f557b8
5
5
  SHA512:
6
- metadata.gz: 94cc269c2fcaf2f71a40ed8e2cebf134d9a3441abdcc4ef17b44f0ed3517b1c2f57fb67fa90e6ba76cef4ef20a64d12de2fc60a06e143bc80bf4bf922dbda8da
7
- data.tar.gz: 6f752941bf65bd8452daa06a86ee04a77059aadff2768974e19e0b3928b752fc70d2b34b4c8abe8023a0578bf4ef6600ca88fb737b9a273672348e0d5ec508d7
6
+ metadata.gz: f9d7e3f1151c101a757688053d3d8f82f446db64e7bacabb72ee9baa064f1221f6489ec6d891201eba9c2284158ae6f59c2c31300918d84be75d10d6ad9cb674
7
+ data.tar.gz: bde7f3cf399c8e069ab48bdf7fc48b93f1aad29ef6d2fbbdb2dad7684291ab28f2bf9ad0cafc37d05227ed443e87c951992519636f640df26e746eef1d06fb66
@@ -3,7 +3,7 @@ FileName:
3
3
  - lib/lita-locker.rb
4
4
 
5
5
  LineLength:
6
- Max: 130
6
+ Max: 150
7
7
 
8
8
  AbcSize:
9
9
  Max: 34
@@ -12,4 +12,7 @@ MethodLength:
12
12
  Max: 20
13
13
 
14
14
  ClassLength:
15
- Max: 150
15
+ Max: 151
16
+
17
+ Metrics/BlockLength:
18
+ Enabled: false
@@ -0,0 +1 @@
1
+ 2.4.2
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
- - 2.2
3
+ - 2.4
5
4
  cache: bundler
6
5
  sudo: false
7
6
  services:
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/README.md CHANGED
@@ -19,7 +19,16 @@ gem "lita-locker"
19
19
 
20
20
  ## Configuration
21
21
 
22
- None
22
+ ### Optional attributes
23
+
24
+ * `per_page` - The number of items to show at once when listing labels or resources. Default: 10
25
+
26
+ ### Example
27
+
28
+ ``` ruby
29
+ Lita.configure do |config|
30
+ config.handlers.locker.per_page = 3
31
+ ```
23
32
 
24
33
  ## Usage
25
34
 
@@ -61,7 +70,7 @@ locker dequeue <label> - Remove yourself from the queue for <label>
61
70
 
62
71
  ### Labels
63
72
  ```
64
- locker label list - List all labels
73
+ locker label list [--page N] - List all labels
65
74
  locker label create <name> - Create a label with <name>.
66
75
  locker label delete <name> - Delete the label with <name>. Clears all locks associated.
67
76
  locker label add <resource> to <name> - Adds <resource> to the list of things to lock/unlock for <name>
@@ -71,10 +80,10 @@ locker label show <name> - Show all resources for <name>
71
80
 
72
81
  ### Resources
73
82
  ```
74
- locker resource list - List all resources
75
- locker resource create <name> - Create a resource with <name>. (Restricted to locker_admins group)
76
- locker resource delete <name> - Delete the resource with <name>. Clears all locks associated. (Restricted to locker_admins group)
77
- locker resource show <name> - Show the state of <name>
83
+ locker resource list [--page N] - List all resources
84
+ locker resource create <name> - Create a resource with <name>. (Restricted to locker_admins group)
85
+ locker resource delete <name> - Delete the resource with <name>. Clears all locks associated. (Restricted to locker_admins group)
86
+ locker resource show <name> - Show the state of <name>
78
87
  ```
79
88
 
80
89
  ### HTTP access
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
3
5
  require 'rubocop/rake_task'
@@ -5,4 +7,4 @@ require 'rubocop/rake_task'
5
7
  RSpec::Core::RakeTask.new(:spec)
6
8
  RuboCop::RakeTask.new(:rubocop)
7
9
 
8
- task default: [:spec, :rubocop]
10
+ task default: %i[spec rubocop]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'lita'
2
4
 
3
5
  Lita.load_locales Dir[File.expand_path(
@@ -6,6 +8,7 @@ Lita.load_locales Dir[File.expand_path(
6
8
 
7
9
  require 'redis-objects'
8
10
  require 'time-lord'
11
+ require 'lita-keyword-arguments'
9
12
 
10
13
  require 'locker/label'
11
14
  require 'locker/misc'
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lita
2
4
  # Handy, isn't it?
3
5
  module Handlers
4
6
  # Top-level class for Locker
5
7
  class Locker < Handler
8
+ config :per_page, type: Integer, default: 10
9
+
6
10
  on :loaded, :setup_redis
7
11
 
8
12
  include ::Locker::Label
@@ -72,7 +76,7 @@ module Lita
72
76
 
73
77
  return response.reply(failed(t('label.does_not_exist', name: name))) unless Label.exists?(name)
74
78
  l = Label.new(name)
75
- return response.reply(failed(t('label.no_resources', name: name))) unless l.membership.count > 0
79
+ return response.reply(failed(t('label.no_resources', name: name))) unless l.membership.count.positive?
76
80
  return response.reply(t('label.self_lock', name: name, user: response.user.name)) if l.owner == response.user
77
81
  return response.reply(success(t('label.lock', name: name))) if l.lock!(response.user.id)
78
82
 
@@ -134,10 +138,12 @@ module Lita
134
138
  l = Label.new(name)
135
139
  return response.reply(failed(t('give.not_owned', label: name))) unless l.locked?
136
140
  owner_mention = render_template('mention', name: l.owner.mention_name, id: l.owner.id)
137
- return response.reply(t('give.not_owner',
138
- label: name,
139
- owner: l.owner.name,
140
- mention: owner_mention)) unless l.owner == response.user
141
+ unless l.owner == response.user
142
+ return response.reply(t('give.not_owner',
143
+ label: name,
144
+ owner: l.owner.name,
145
+ mention: owner_mention))
146
+ end
141
147
  recipient_name = response.match_data['username'].rstrip
142
148
  recipient = Lita::User.fuzzy_find(recipient_name)
143
149
  return response.reply(t('user.unknown', user: recipient_name)) unless recipient
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lita
2
4
  module Handlers
3
5
  # Event-related handlers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lita
2
4
  module Handlers
3
5
  # HTTP-related handlers
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'locker/list'
4
+
1
5
  module Lita
2
6
  module Handlers
3
7
  # Label-related handlers
@@ -10,64 +14,77 @@ module Lita
10
14
  include ::Locker::Resource
11
15
 
12
16
  route(
13
- /^locker\slabel\slist$/,
17
+ /^locker\slabel\slist/,
14
18
  :list,
15
19
  command: true,
20
+ kwargs: { page: { default: 1 } },
16
21
  help: { t('help.label.list.syntax') => t('help.label.list.desc') }
17
22
  )
18
23
 
19
24
  route(
20
- /^locker\slabel\screate\s#{LABELS_REGEX}$/,
25
+ /^locker\slabel\screate\s#{LABELS_REGEX}#{COMMENT_REGEX}$/,
21
26
  :create,
22
27
  command: true,
23
28
  help: { t('help.label.create.syntax') => t('help.label.create.desc') }
24
29
  )
25
30
 
26
31
  route(
27
- /^locker\slabel\sdelete\s#{LABELS_REGEX}$/,
32
+ /^locker\slabel\sdelete\s#{LABELS_REGEX}#{COMMENT_REGEX}$/,
28
33
  :delete,
29
34
  command: true,
30
35
  help: { t('help.label.delete.syntax') => t('help.label.delete.desc') }
31
36
  )
32
37
 
33
38
  route(
34
- /^locker\slabel\sshow\s#{LABEL_REGEX}$/,
39
+ /^locker\slabel\sshow\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
35
40
  :show,
36
41
  command: true,
37
42
  help: { t('help.label.show.syntax') => t('help.label.show.desc') }
38
43
  )
39
44
 
40
45
  route(
41
- /^locker\slabel\sadd\s#{RESOURCES_REGEX}\sto\s#{LABEL_REGEX}$/,
46
+ /^locker\slabel\sadd\s#{RESOURCES_REGEX}\sto\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
42
47
  :add,
43
48
  command: true,
44
49
  help: { t('help.label.add.syntax') => t('help.label.add.desc') }
45
50
  )
46
51
 
47
52
  route(
48
- /^locker\slabel\sremove\s#{RESOURCES_REGEX}\sfrom\s#{LABEL_REGEX}$/,
53
+ /^locker\slabel\sremove\s#{RESOURCES_REGEX}\sfrom\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
49
54
  :remove,
50
55
  command: true,
51
56
  help: { t('help.label.remove.syntax') => t('help.label.remove.desc') }
52
57
  )
53
58
 
54
59
  def list(response)
55
- after 0 do
56
- should_rate_limit = false
60
+ begin
61
+ list = ::Locker::List.new(Label, config.per_page, response.extensions[:kwargs][:page])
62
+ rescue ArgumentError
63
+ return response.reply(t('list.invalid_page_type'))
64
+ end
57
65
 
58
- Label.list.each_slice(5) do |slice|
59
- if should_rate_limit
60
- sleep 3
61
- else
62
- should_rate_limit = true
63
- end
66
+ return response.reply(t('list.page_outside_range', pages: list.pages)) unless list.valid_page?
64
67
 
65
- slice.each do |n|
66
- l = Label.new(n)
67
- response.reply(unlocked(t('label.desc', name: n, state: l.state.value)))
68
- end
68
+ message = list.requested_page.map do |key|
69
+ label = Label.new(key)
70
+
71
+ state = label.state.value.to_s
72
+
73
+ case state
74
+ when 'unlocked'
75
+ unlocked(t('label.desc', name: key, state: state))
76
+ when 'locked'
77
+ locked(t('label.desc', name: key, state: state))
78
+ else
79
+ # This case shouldn't happen, but it will if a label
80
+ # gets saved with some other value for `state`.
81
+ t('label.desc', name: key, state: state)
69
82
  end
70
- end
83
+ end.join("\n")
84
+
85
+ message += "\n#{t('list.paginate', page: list.page, pages: list.pages)}" if list.multiple_pages?
86
+
87
+ response.reply(message)
71
88
  end
72
89
 
73
90
  def create(response)
@@ -104,7 +121,7 @@ module Lita
104
121
  name = response.match_data['label']
105
122
  return response.reply(failed(t('label.does_not_exist', name: name))) unless Label.exists?(name)
106
123
  l = Label.new(name)
107
- return response.reply(t('label.has_no_resources', name: name)) unless l.membership.count > 0
124
+ return response.reply(t('label.has_no_resources', name: name)) unless l.membership.count.positive?
108
125
  res = []
109
126
  l.membership.each do |member|
110
127
  res.push(member)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Lita
2
4
  module Handlers
3
5
  # Misc Locker handlers
@@ -10,28 +12,28 @@ module Lita
10
12
  include ::Locker::Resource
11
13
 
12
14
  route(
13
- /^locker\sstatus\s#{LABEL_WILDCARD_REGEX}$/,
15
+ /^locker\sstatus\s#{LABEL_WILDCARD_REGEX}#{COMMENT_REGEX}$/,
14
16
  :status,
15
17
  command: true,
16
18
  help: { t('help.status.syntax') => t('help.status.desc') }
17
19
  )
18
20
 
19
21
  route(
20
- /^locker\slist\s#{USER_REGEX}$/,
22
+ /^locker\slist\s#{USER_REGEX}#{COMMENT_REGEX}$/,
21
23
  :list,
22
24
  command: true,
23
25
  help: { t('help.list.syntax') => t('help.list.desc') }
24
26
  )
25
27
 
26
28
  route(
27
- /^locker\s(dq|dequeue)\s#{LABEL_REGEX}$/,
29
+ /^locker\s(dq|dequeue)\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
28
30
  :dequeue,
29
31
  command: true,
30
32
  help: { t('help.dequeue.syntax') => t('help.dequeue.desc') }
31
33
  )
32
34
 
33
35
  route(
34
- /^locker\slog\s#{LABEL_REGEX}$/,
36
+ /^locker\slog\s#{LABEL_REGEX}#{COMMENT_REGEX}$/,
35
37
  :log,
36
38
  command: true,
37
39
  help: { t('help.log.syntax.') => t('help.log.desc') }
@@ -48,7 +50,7 @@ module Lita
48
50
 
49
51
  def status(response)
50
52
  name = response.match_data['label']
51
- unless name =~ /\*/
53
+ unless name.match?(/\*/)
52
54
  # Literal query
53
55
  return response.reply(status_label(name)) if Label.exists?(name)
54
56
  return response.reply(status_resource(name)) if Resource.exists?(name)
@@ -90,7 +92,7 @@ module Lita
90
92
  def status_label(name)
91
93
  l = Label.new(name)
92
94
  return unlocked(t('label.desc', name: name, state: l.state.value)) unless l.locked?
93
- if l.wait_queue.count > 0
95
+ if l.wait_queue.count.positive?
94
96
  queue = []
95
97
  l.wait_queue.each do |u|
96
98
  usr = Lita::User.find_by_id(u)
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'locker/list'
4
+
1
5
  module Lita
2
6
  module Handlers
3
7
  # Resource-related handlers
@@ -10,14 +14,15 @@ module Lita
10
14
  include ::Locker::Resource
11
15
 
12
16
  route(
13
- /^locker\sresource\slist$/,
17
+ /^locker\sresource\slist/,
14
18
  :list,
15
19
  command: true,
20
+ kwargs: { page: { default: 1 } },
16
21
  help: { t('help.resource.list.syntax') => t('help.resource.list.desc') }
17
22
  )
18
23
 
19
24
  route(
20
- /^locker\sresource\screate\s#{RESOURCES_REGEX}$/,
25
+ /^locker\sresource\screate\s#{RESOURCES_REGEX}#{COMMENT_REGEX}$/,
21
26
  :create,
22
27
  command: true,
23
28
  restrict_to: [:locker_admins],
@@ -27,7 +32,7 @@ module Lita
27
32
  )
28
33
 
29
34
  route(
30
- /^locker\sresource\sdelete\s#{RESOURCES_REGEX}$/,
35
+ /^locker\sresource\sdelete\s#{RESOURCES_REGEX}#{COMMENT_REGEX}$/,
31
36
  :delete,
32
37
  command: true,
33
38
  restrict_to: [:locker_admins],
@@ -37,29 +42,41 @@ module Lita
37
42
  )
38
43
 
39
44
  route(
40
- /^locker\sresource\sshow\s#{RESOURCE_REGEX}$/,
45
+ /^locker\sresource\sshow\s#{RESOURCE_REGEX}#{COMMENT_REGEX}$/,
41
46
  :show,
42
47
  command: true,
43
48
  help: { t('help.resource.show.syntax') => t('help.resource.show.desc') }
44
49
  )
45
50
 
46
51
  def list(response)
47
- after 0 do
48
- should_rate_limit = false
49
-
50
- Resource.list.each_slice(5) do |slice|
51
- if should_rate_limit
52
- sleep 3
53
- else
54
- should_rate_limit = true
55
- end
56
-
57
- slice.each do |r|
58
- res = Resource.new(r)
59
- response.reply(t('resource.desc', name: r, state: res.state.value))
60
- end
61
- end
52
+ begin
53
+ list = ::Locker::List.new(Resource, config.per_page, response.extensions[:kwargs][:page])
54
+ rescue ArgumentError
55
+ return response.reply(t('list.invalid_page_type'))
62
56
  end
57
+
58
+ return response.reply(t('list.page_outside_range', pages: list.pages)) unless list.valid_page?
59
+
60
+ message = list.requested_page.map do |key|
61
+ resource = Resource.new(key)
62
+
63
+ state = resource.state.value
64
+
65
+ case state
66
+ when 'unlocked'
67
+ unlocked(t('resource.desc', name: key, state: state))
68
+ when 'locked'
69
+ locked(t('resource.desc', name: key, state: state))
70
+ else
71
+ # This case shouldn't happen, but it will if a label
72
+ # gets saved with some other value for `state`.
73
+ t('resource.desc', name: key, state: state)
74
+ end
75
+ end.join("\n")
76
+
77
+ message += "\n#{t('list.paginate', page: list.page, pages: list.pages)}" if list.multiple_pages?
78
+
79
+ response.reply(message)
63
80
  end
64
81
 
65
82
  def create(response)
@@ -99,7 +116,7 @@ module Lita
99
116
  return response.reply(t('resource.does_not_exist', name: name)) unless Resource.exists?(name)
100
117
  r = Resource.new(name)
101
118
  resp = t('resource.desc', name: name, state: r.state.value)
102
- if r.labels.count > 0
119
+ if r.labels.count.positive?
103
120
  resp += ', used by: '
104
121
  r.labels.each do |label|
105
122
  resp += Label.new(label).id
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Locker subsystem
2
4
  module Locker
3
5
  # Label helpers
@@ -40,7 +42,7 @@ module Locker
40
42
 
41
43
  def self.delete(key)
42
44
  raise 'Unknown label key' unless Label.exists?(key)
43
- %w(state, owner_id, membership, wait_queue, journal, observer_ids).each do |item|
45
+ %w[state owner_id membership wait_queue journal observer_ids].each do |item|
44
46
  redis.del("label:#{key}:#{item}")
45
47
  end
46
48
  redis.srem('label-list', Label.normalize(key))
@@ -93,7 +95,7 @@ module Locker
93
95
  log('Unlocked')
94
96
 
95
97
  # FIXME: Possible race condition where resources become unavailable between unlock and relock
96
- if wait_queue.count > 0
98
+ if wait_queue.count.positive?
97
99
  next_user = wait_queue.shift
98
100
  lock!(next_user)
99
101
  end
@@ -207,9 +209,7 @@ module Locker
207
209
  l = Label.new(name)
208
210
  l.membership.each do |resource_name|
209
211
  resource = Locker::Resource::Resource.new(resource_name)
210
- if resource.state.value == 'locked'
211
- deps.push "#{resource_name} - #{resource.owner.name}"
212
- end
212
+ deps.push "#{resource_name} - #{resource.owner.name}" if resource.state.value == 'locked'
213
213
  end
214
214
  msg += deps.join("\n")
215
215
  msg
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Locker subsystem
4
+ module Locker
5
+ # A paginated list of items (e.g. labels or resources).
6
+ #
7
+ # @api private
8
+ class List
9
+ # @return [#list] The Ruby class of the item to be listed.
10
+ attr_reader :item_class
11
+
12
+ # @return [Enumerable] The full list of items.
13
+ attr_reader :list
14
+
15
+ # @return [Integer] The number of items displayed per page.
16
+ attr_reader :per_page
17
+
18
+ # @return [Integer] The page the user has requested.
19
+ attr_reader :page
20
+
21
+ # @return [Integer] The total number of pages.
22
+ attr_reader :pages
23
+
24
+ # @return [Integer] The zero-based index offset that the requested page starts on within the full list.
25
+ attr_reader :offset
26
+
27
+ def initialize(item_class, per_page, page)
28
+ @item_class = item_class
29
+ @list = item_class.list
30
+ @per_page = per_page
31
+ @page = Integer(page.to_s, 10)
32
+ @pages = (list.count / per_page).ceil + 1
33
+ @offset = per_page * (self.page - 1)
34
+ end
35
+
36
+ # Whether or not the list has multiple pages.
37
+ #
38
+ # @return [Boolean]
39
+ def multiple_pages?
40
+ list.count > per_page
41
+ end
42
+
43
+ # An enumerable of the items in the requested page.
44
+ #
45
+ # @return [Enumerable]
46
+ def requested_page
47
+ list[offset, per_page]
48
+ end
49
+
50
+ # Whether or not the requested page exists.
51
+ #
52
+ # @return [Boolean]
53
+ def valid_page?
54
+ page >= 1 && page <= pages
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Locker subsystem
2
4
  module Locker
3
5
  # Misc helpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Locker subsystem
2
4
  module Locker
3
5
  # Regex definitions
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Locker subsystem
2
4
  module Locker
3
5
  # Resource helpers
@@ -34,7 +36,7 @@ module Locker
34
36
 
35
37
  def self.delete(key)
36
38
  raise 'Unknown resource key' unless Resource.exists?(key)
37
- %w(state, owner_id).each do |item|
39
+ %w[state owner_id].each do |item|
38
40
  redis.del("resource:#{key}:#{item}")
39
41
  end
40
42
  redis.srem('resource-list', key)
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Gem::Specification.new do |spec|
2
4
  spec.name = 'lita-locker'
3
- spec.version = '1.0.10'
5
+ spec.version = '1.1.0'
4
6
  spec.authors = ['Eric Sigler']
5
7
  spec.email = ['me@esigler.com']
6
8
  spec.description = '"lock" and "unlock" arbitrary subjects'
@@ -15,6 +17,7 @@ Gem::Specification.new do |spec|
15
17
  spec.require_paths = ['lib']
16
18
 
17
19
  spec.add_runtime_dependency 'lita', '>= 4.2'
20
+ spec.add_runtime_dependency 'lita-keyword-arguments'
18
21
  spec.add_runtime_dependency 'redis-objects'
19
22
  spec.add_runtime_dependency 'time-lord'
20
23
 
@@ -16,6 +16,10 @@ en:
16
16
  already_observing: "%{user}, you are already observing %{name}"
17
17
  stopped_observing: "%{user}, you have stopped observing %{name}"
18
18
  were_not_observing: "%{user}, you were not observing %{name}"
19
+ list:
20
+ paginate: "Page %{page} of %{pages} shown. Use --page to specify additional pages."
21
+ invalid_page_type: "Page specified must be an integer."
22
+ page_outside_range: "Page specified must be between 1 and %{pages}."
19
23
  help:
20
24
  log:
21
25
  syntax: locker log <label>
@@ -49,7 +53,7 @@ en:
49
53
  desc: Show what locks a user currently holds
50
54
  resource:
51
55
  list:
52
- syntax: locker resource list
56
+ syntax: locker resource list [--page N]
53
57
  desc: List all resources
54
58
  create:
55
59
  syntax: "locker resource create <name>[, <name> ...]"
@@ -62,7 +66,7 @@ en:
62
66
  desc: Show the state of <name>
63
67
  label:
64
68
  list:
65
- syntax: locker label list
69
+ syntax: locker label list [--page N]
66
70
  desc: List all labels
67
71
  create:
68
72
  syntax: "locker label create <name>[, <name> ...]"
@@ -105,7 +109,7 @@ en:
105
109
  unlocked_no_queue: "%{name} is unlocked and no one is next up %{mention}"
106
110
  unable_to_lock: "%{name} unable to be locked"
107
111
  lock: "%{name} locked"
108
- desc: "%{name} is unlocked"
112
+ desc: "%{name} is %{state}"
109
113
  desc_owner: "%{name} is locked by %{owner_name} (taken %{time})"
110
114
  desc_owner_queue: "%{name} is locked by %{owner_name} (taken %{time}). Next up: %{queue}"
111
115
  created: "Label %{name} created"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::LockerEvents, lita_handler: true do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::LockerHttp, lita_handler: true do
@@ -24,7 +26,7 @@ describe Lita::Handlers::LockerHttp, lita_handler: true do
24
26
  it 'shows json if the label exists' do
25
27
  send_command('locker label create foo')
26
28
  subject.label_show(request, response)
27
- expect(response.body).to eq(['{"id":"foo","state":"unlocked","membership":""}'])
29
+ expect(response.body).to eq(['{"id":"foo","state":"unlocked","membership":{"key":"label:foo:membership","options":{"type":"set"},"value":[]}}'])
28
30
  end
29
31
 
30
32
  it 'shows 404 if the label does not exist' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::LockerLabels, lita_handler: true do
@@ -17,6 +19,12 @@ describe Lita::Handlers::LockerLabels, lita_handler: true do
17
19
  is_expected.to route_command("locker label add foo, bar to #{l}").to(:add)
18
20
  is_expected.to route_command("locker label remove resource from #{l}").to(:remove)
19
21
  is_expected.to route_command("locker label remove foo, bar from #{l}").to(:remove)
22
+
23
+ is_expected.to route_command("locker label create #{l} # comment").to(:create)
24
+ is_expected.to route_command("locker label delete #{l} # comment").to(:delete)
25
+ is_expected.to route_command("locker label show #{l} # comment").to(:show)
26
+ is_expected.to route_command("locker label add resource to #{l} # comment").to(:add)
27
+ is_expected.to route_command("locker label remove resource from #{l} # comment").to(:remove)
20
28
  end
21
29
  end
22
30
 
@@ -33,12 +41,55 @@ describe Lita::Handlers::LockerLabels, lita_handler: true do
33
41
 
34
42
  describe '#label_list' do
35
43
  it 'shows a list of labels if there are any' do
44
+ send_command('locker resource create whatever')
36
45
  send_command('locker label create foobar')
37
46
  send_command('locker label create bazbat')
47
+ send_command('locker label add whatever to bazbat')
48
+ send_command('lock bazbat')
38
49
  send_command('locker label list')
39
- sleep 1 # TODO: HAAAACK. Need after to have a more testable behavior.
40
- expect(replies.include?('foobar is unlocked')).to eq(true)
41
- expect(replies.include?('bazbat is unlocked')).to eq(true)
50
+ expect(replies.last).to include('foobar is unlocked')
51
+ expect(replies.last).to include('bazbat is locked')
52
+ end
53
+
54
+ context 'when per_page is configured to 3' do
55
+ before do
56
+ robot.config.handlers.locker.per_page = 3
57
+ end
58
+
59
+ context 'when there are 4 labels' do
60
+ before do
61
+ send_command('locker label create 1')
62
+ send_command('locker label create 2')
63
+ send_command('locker label create 3')
64
+ send_command('locker label create 4')
65
+ end
66
+
67
+ it 'includes details about what page was shown' do
68
+ send_command('locker label list')
69
+ expect(replies.last).to include('Page 1 of 2 shown. Use --page to specify additional pages.')
70
+ end
71
+
72
+ it 'displays the page specified' do
73
+ send_command('locker label list --page 2')
74
+ expect(replies.last).to include('4 is unlocked')
75
+ expect(replies.last).to include('Page 2 of 2 shown. Use --page to specify additional pages.')
76
+ end
77
+
78
+ it 'rejects pages lower than 1' do
79
+ send_command('locker label list --page 0')
80
+ expect(replies.last).to eq('Page specified must be between 1 and 2.')
81
+ end
82
+
83
+ it 'rejects pages higher than the number there are' do
84
+ send_command('locker label list --page 3')
85
+ expect(replies.last).to eq('Page specified must be between 1 and 2.')
86
+ end
87
+ end
88
+
89
+ it 'rejects non-integer values for pages' do
90
+ send_command('locker label list --page x')
91
+ expect(replies.last).to eq('Page specified must be an integer.')
92
+ end
42
93
  end
43
94
  end
44
95
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::LockerMisc, lita_handler: true do
@@ -18,19 +20,23 @@ describe Lita::Handlers::LockerMisc, lita_handler: true do
18
20
  end
19
21
 
20
22
  it { is_expected.to route_command('locker status foo*').to(:status) }
23
+ it { is_expected.to route_command('locker status foo* # comment').to(:status) }
21
24
 
22
25
  it do
23
26
  is_expected.to route_command('locker list @alice').to(:list)
24
27
  is_expected.to route_command('locker list Alice').to(:list)
28
+ is_expected.to route_command('locker list Alice # comment').to(:list)
25
29
  end
26
30
 
27
31
  it do
28
32
  is_expected.to route_command('locker log something').to(:log)
33
+ is_expected.to route_command('locker log something # comment').to(:log)
29
34
  end
30
35
 
31
36
  it do
32
37
  is_expected.to route_command('locker dequeue something something').to(:dequeue)
33
38
  is_expected.to route_command('locker dq something something').to(:dequeue)
39
+ is_expected.to route_command('locker dq something something # comment').to(:dequeue)
34
40
  end
35
41
 
36
42
  let(:alice) do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::LockerResources, lita_handler: true do
@@ -12,6 +14,9 @@ describe Lita::Handlers::LockerResources, lita_handler: true do
12
14
  is_expected.to route_command("locker resource create #{r}").to(:create)
13
15
  is_expected.to route_command("locker resource delete #{r}").to(:delete)
14
16
  is_expected.to route_command("locker resource show #{r}").to(:show)
17
+ is_expected.to route_command("locker resource create #{r} # comment").to(:create)
18
+ is_expected.to route_command("locker resource delete #{r} # comment").to(:delete)
19
+ is_expected.to route_command("locker resource show #{r} # comment").to(:show)
15
20
  end
16
21
  end
17
22
 
@@ -25,15 +30,56 @@ describe Lita::Handlers::LockerResources, lita_handler: true do
25
30
  end
26
31
 
27
32
  it { is_expected.to route_command('locker resource list').to(:list) }
33
+ it { is_expected.to route_command('locker resource list # comment').to(:list) }
28
34
 
29
35
  describe '#resource_list' do
30
36
  it 'shows a list of resources if there are any' do
31
37
  send_command('locker resource create foobar')
32
38
  send_command('locker resource create bazbat')
33
39
  send_command('locker resource list')
34
- sleep 1 # TODO: HAAAAACK. Need after to have a more testable behavior.
35
- expect(replies).to include('Resource: foobar, state: unlocked')
36
- expect(replies).to include('Resource: bazbat, state: unlocked')
40
+ expect(replies.last).to include('Resource: foobar, state: unlocked')
41
+ expect(replies.last).to include('Resource: bazbat, state: unlocked')
42
+ end
43
+
44
+ context 'when per_page is configured to 3' do
45
+ before do
46
+ robot.config.handlers.locker.per_page = 3
47
+ end
48
+
49
+ context 'when there are 4 resources' do
50
+ before do
51
+ send_command('locker resource create 1')
52
+ send_command('locker resource create 2')
53
+ send_command('locker resource create 3')
54
+ send_command('locker resource create 4')
55
+ end
56
+
57
+ it 'includes details about what page was shown' do
58
+ send_command('locker resource list')
59
+ expect(replies.last).to include('Page 1 of 2 shown. Use --page to specify additional pages.')
60
+ end
61
+
62
+ it 'displays the page specified' do
63
+ send_command('locker resource list --page 2')
64
+ expect(replies.last).to include('Resource: 4, state: unlocked')
65
+ expect(replies.last).to include('Page 2 of 2 shown. Use --page to specify additional pages.')
66
+ end
67
+
68
+ it 'rejects pages lower than 1' do
69
+ send_command('locker resource list --page 0')
70
+ expect(replies.last).to eq('Page specified must be between 1 and 2.')
71
+ end
72
+
73
+ it 'rejects pages higher than the number there are' do
74
+ send_command('locker resource list --page 3')
75
+ expect(replies.last).to eq('Page specified must be between 1 and 2.')
76
+ end
77
+ end
78
+
79
+ it 'rejects non-integer values for pages' do
80
+ send_command('locker resource list --page x')
81
+ expect(replies.last).to eq('Page specified must be an integer.')
82
+ end
37
83
  end
38
84
  end
39
85
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Lita::Handlers::Locker, lita_handler: true do
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Locker::List do
6
+ let(:item_class) { double('item class', list: [one, two, three, four]) }
7
+
8
+ let(:one) { double('one') }
9
+ let(:two) { double('two') }
10
+ let(:three) { double('three') }
11
+ let(:four) { double('four') }
12
+
13
+ it 'raises an argument error if a non-integer page is requested' do
14
+ expect { described_class.new(item_class, 3, 'z') }.to raise_error(ArgumentError)
15
+ end
16
+
17
+ describe '#multiple_pages' do
18
+ it 'is true when there are more total items than can be displayed on one page' do
19
+ subject = described_class.new(item_class, 1, 1)
20
+
21
+ expect(subject).to be_multiple_pages
22
+ end
23
+
24
+ it 'is false when the whole list fits in one page' do
25
+ subject = described_class.new(item_class, 10, 1)
26
+
27
+ expect(subject).not_to be_multiple_pages
28
+ end
29
+ end
30
+
31
+ describe '#requested_page' do
32
+ context 'with an empty list' do
33
+ let(:item_class) { double('item class', list: []) }
34
+
35
+ it 'returns an empty list' do
36
+ subject = described_class.new(item_class, 3, 1)
37
+
38
+ expect(subject.requested_page).to be_empty
39
+ end
40
+ end
41
+
42
+ context 'with a single item list' do
43
+ let(:item_class) { double('item class', list: [one]) }
44
+
45
+ it 'returns a list with one item' do
46
+ subject = described_class.new(item_class, 3, 1)
47
+
48
+ expect(subject.requested_page).to eq([one])
49
+ end
50
+ end
51
+
52
+ context 'with a four item list' do
53
+ it 'splits the pages correctly when there are two items per page' do
54
+ subject = described_class.new(item_class, 2, 1)
55
+
56
+ expect(subject.requested_page).to eq([one, two])
57
+
58
+ subject = described_class.new(item_class, 2, 2)
59
+
60
+ expect(subject.requested_page).to eq([three, four])
61
+ end
62
+
63
+ it 'splits the pages correctly when there are three items per page' do
64
+ subject = described_class.new(item_class, 3, 1)
65
+
66
+ expect(subject.requested_page).to eq([one, two, three])
67
+
68
+ subject = described_class.new(item_class, 3, 2)
69
+
70
+ expect(subject.requested_page).to eq([four])
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#valid_page?' do
76
+ it 'is true when the first page is requested' do
77
+ subject = described_class.new(item_class, 3, 1)
78
+
79
+ expect(subject).to be_valid_page
80
+ end
81
+
82
+ it 'is true when the page is between 1 and the total number of pages' do
83
+ subject = described_class.new(item_class, 3, 2)
84
+
85
+ expect(subject).to be_valid_page
86
+ end
87
+
88
+ it 'is false when the page is less than 1' do
89
+ subject = described_class.new(item_class, 3, 0)
90
+
91
+ expect(subject).not_to be_valid_page
92
+ end
93
+
94
+ it 'is false when the page is greater than the total number of pages' do
95
+ subject = described_class.new(item_class, 3, 10)
96
+
97
+ expect(subject).not_to be_valid_page
98
+ end
99
+ end
100
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'simplecov'
2
4
  require 'coveralls'
3
5
  SimpleCov.formatters = [
@@ -12,12 +14,15 @@ Lita.version_3_compatibility_mode = false
12
14
 
13
15
  RSpec.configure do |config|
14
16
  config.before do
15
- registry.register_handler(Lita::Handlers::Locker)
16
- registry.register_handler(Lita::Handlers::LockerEvents)
17
- registry.register_handler(Lita::Handlers::LockerHttp)
18
- registry.register_handler(Lita::Handlers::LockerLabels)
19
- registry.register_handler(Lita::Handlers::LockerMisc)
20
- registry.register_handler(Lita::Handlers::LockerResources)
17
+ if defined? registry
18
+ registry.register_hook(:trigger_route, Lita::Extensions::KeywordArguments)
19
+ registry.register_handler(Lita::Handlers::Locker)
20
+ registry.register_handler(Lita::Handlers::LockerEvents)
21
+ registry.register_handler(Lita::Handlers::LockerHttp)
22
+ registry.register_handler(Lita::Handlers::LockerLabels)
23
+ registry.register_handler(Lita::Handlers::LockerMisc)
24
+ registry.register_handler(Lita::Handlers::LockerResources)
25
+ end
21
26
  end
22
27
  end
23
28
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-locker
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.10
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Sigler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-06 00:00:00.000000000 Z
11
+ date: 2018-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: lita-keyword-arguments
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: redis-objects
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -146,6 +160,7 @@ files:
146
160
  - ".gitignore"
147
161
  - ".rspec"
148
162
  - ".rubocop.yml"
163
+ - ".ruby-version"
149
164
  - ".travis.yml"
150
165
  - CONTRIBUTING.md
151
166
  - Gemfile
@@ -161,6 +176,7 @@ files:
161
176
  - lib/lita/handlers/locker_misc.rb
162
177
  - lib/lita/handlers/locker_resources.rb
163
178
  - lib/locker/label.rb
179
+ - lib/locker/list.rb
164
180
  - lib/locker/misc.rb
165
181
  - lib/locker/regex.rb
166
182
  - lib/locker/resource.rb
@@ -172,6 +188,7 @@ files:
172
188
  - spec/lita/handlers/locker_misc_spec.rb
173
189
  - spec/lita/handlers/locker_resources_spec.rb
174
190
  - spec/lita/handlers/locker_spec.rb
191
+ - spec/locker/list_spec.rb
175
192
  - spec/spec_helper.rb
176
193
  - templates/failed.erb
177
194
  - templates/failed.hipchat.erb
@@ -209,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
226
  version: '0'
210
227
  requirements: []
211
228
  rubyforge_project:
212
- rubygems_version: 2.4.5
229
+ rubygems_version: 2.6.13
213
230
  signing_key:
214
231
  specification_version: 4
215
232
  summary: '"lock" and "unlock" arbitrary subjects'
@@ -220,4 +237,5 @@ test_files:
220
237
  - spec/lita/handlers/locker_misc_spec.rb
221
238
  - spec/lita/handlers/locker_resources_spec.rb
222
239
  - spec/lita/handlers/locker_spec.rb
240
+ - spec/locker/list_spec.rb
223
241
  - spec/spec_helper.rb