list-tool 1.0.3 → 1.0.5

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.
@@ -1,31 +1,31 @@
1
1
  module ListTool
2
2
  module App
3
3
 
4
- class UseCommand
4
+ class UseCommand < Command
5
+ class << self
5
6
 
6
- def self.match? arg
7
- ['u', 'use'].include? arg
8
- end
7
+ def match? arg
8
+ ['u', 'use'].include? arg
9
+ end
9
10
 
10
- def self.parse argv
11
- raise ArgumentError, "expected argument to be an array, #{argv.class} given" unless argv.is_a? Array
12
- list = argv.shift
13
- raise ArgumentError, "list number not specified" if list.nil?
11
+ def parse argv
12
+ fail_if_not_an_array(argv)
13
+
14
+ list = argv.shift
14
15
 
15
- list = Integer( list ) - 1 rescue raise(ArgumentError, 'list number must be an integer')
16
- raise ArgumentError, "list number can't be less than 1" if list < 0
16
+ { list: parse_list_number!(list) }
17
+ end
17
18
 
18
- {list: list}
19
- end
19
+ def execute options, lister
20
+ raise(ListNotFoundError, 'no list with given number') if lister.set_default_list( options[:list] ).nil?
21
+ end
20
22
 
21
- def self.execute options, lister
22
- raise(ListNotFoundError, 'no list with given number') if lister.set_default_list( options[:list] ).nil?
23
- end
23
+ def help
24
+ " u, use LIST\t\t\tSet default list"
25
+ end
24
26
 
25
- def self.help
26
- " u, use LIST\t\t\tSet default list"
27
27
  end
28
-
29
28
  end
29
+
30
30
  end
31
31
  end
@@ -1,24 +1,27 @@
1
1
  module ListTool
2
2
  module App
3
3
 
4
- class VersionCommand
4
+ class VersionCommand < Command
5
+ class << self
5
6
 
6
- def self.match? arg
7
- ['v', '-v', 'version', '--version'].include? arg
8
- end
7
+ def match? arg
8
+ ['v', '-v', 'version', '--version'].include? arg
9
+ end
9
10
 
10
- def self.parse argv
11
- {}
12
- end
11
+ def parse argv
12
+ {}
13
+ end
13
14
 
14
- def self.execute options, lister
15
- Printer.print_version
16
- end
15
+ def execute options, lister
16
+ Printer.print_version
17
+ end
17
18
 
18
- def self.help
19
- " -v, --version\t\t\tPrint version"
20
- end
19
+ def help
20
+ " -v, --version\t\t\tPrint version"
21
+ end
21
22
 
23
+ end
22
24
  end
25
+
23
26
  end
24
27
  end
@@ -1,3 +1,4 @@
1
+ require_relative './commands/command.rb'
1
2
  require_relative './commands/add_item_command.rb'
2
3
  require_relative './commands/replace_item_command.rb'
3
4
  require_relative './commands/delete_item_command.rb'
@@ -5,6 +6,7 @@ require_relative './commands/show_items_command.rb'
5
6
  require_relative './commands/add_list_command.rb'
6
7
  require_relative './commands/rename_list_command.rb'
7
8
  require_relative './commands/delete_list_command.rb'
9
+ require_relative './commands/clear_list_command.rb'
8
10
  require_relative './commands/show_lists_command.rb'
9
11
  require_relative './commands/use_command.rb'
10
12
  require_relative './commands/help_command.rb'
@@ -16,7 +18,7 @@ module ListTool
16
18
 
17
19
  class Commands
18
20
 
19
- COMMANDS = ListTool::App.constants.map {|const| ListTool::App.const_get(const)} - [self, Printer, Runner, Colorizer]
21
+ COMMANDS = ListTool::App.constants.map {|const| ListTool::App.const_get(const)} - [self, Printer, Runner, Colorizer, Command]
20
22
 
21
23
  class << self
22
24
  def process argv, lister
@@ -23,6 +23,10 @@ module ListTool
23
23
  end
24
24
  end
25
25
 
26
+ def inspect
27
+ "#<#{self.class}:0x#{self.__id__.to_s(16)}, name: #{name}, items: [#{items.map(&:text).join(', ')}]>"
28
+ end
29
+
26
30
  def clear!
27
31
  @items = []
28
32
  end
@@ -45,6 +49,7 @@ module ListTool
45
49
 
46
50
  def add_item text
47
51
  @items << Item.new(text)
52
+ @items[-1]
48
53
  end
49
54
 
50
55
  def delete_item num
@@ -37,38 +37,50 @@ module ListTool
37
37
  end
38
38
 
39
39
  def list(index=nil)
40
- list = if index
41
- return nil if @data.lists[index].nil?
42
- @data.lists[index]
43
- else
44
- raise NoDefaultListError, "default list not set" if @data.default_list.nil?
45
- @data.default_list
46
- end
40
+ list = get_list(index)
41
+ return nil if list.nil?
47
42
 
48
43
  { name: list.name, items: list.items.map{|item| item.text} }
49
44
  end
50
45
 
51
- def method_missing(name, *args, &block)
52
- if name =~ /_list$/
53
- object = @data
54
- elsif name =~ /_item$/
55
- object = if args[-1].is_a?(Hash) && args[-1].has_key?(:list)
56
- return nil if @data.lists[ args[-1][:list] ].nil?
57
- index = args.pop()[:list]
58
- @data.lists[index]
59
- else
60
- raise NoDefaultListError, "default list not set" if @data.default_list.nil?
61
- @data.default_list
62
- end
46
+ def default_list
47
+ if @data.default_list
48
+ list = @data.default_list
49
+ { name: list.name, items: list.items.map{|item| item.text} }
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+ def method_missing(method_name, *args, &block)
56
+ if method_name =~ /_list$/
57
+ receiver = @data
58
+ elsif method_name =~ /_item$/
59
+ if args[-1].is_a?(Hash) && args[-1].has_key?(:list)
60
+ # then last argument is an options hash
61
+ options = args.pop
62
+ index = options[:list]
63
+ end
64
+ receiver = get_list(index)
65
+ receiver || raise(ListNotFoundError, "list with given index doesn't exist")
63
66
  else
64
67
  super
65
68
  end
66
69
 
67
- result = object.send(name, *args, &block)
68
- return nil if result.nil?
69
- self
70
+ receiver.send(method_name, *args, &block)
70
71
  rescue NoMethodError => e
71
- raise NoMethodError, "undefined method '#{name.to_s}' for #{self.inspect}"
72
+ raise NoMethodError, "undefined method '#{method_name.to_s}' for #{self.inspect}"
73
+ end
74
+
75
+ private
76
+
77
+ def get_list index=nil
78
+ if index
79
+ @data.lists[index]
80
+ else
81
+ raise NoDefaultListError, "default list not set" if @data.default_list.nil?
82
+ @data.default_list
83
+ end
72
84
  end
73
85
 
74
86
  end
@@ -17,6 +17,10 @@ module ListTool
17
17
  set_default_list(hash['default']) if hash['default']
18
18
  end
19
19
 
20
+ def inspect
21
+ "#<#{self.class}:0x#{self.__id__.to_s(16)}, lists: [#{lists.map(&:name).join(', ')}], default_list: #{default_list.name}>"
22
+ end
23
+
20
24
  def each
21
25
  @lists.each { |list| yield(list) }
22
26
  end
@@ -1,3 +1,3 @@
1
1
  module ListTool
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.5"
3
3
  end
@@ -36,12 +36,6 @@ describe ListTool::App::AddListCommand do
36
36
  end
37
37
  end
38
38
 
39
- context 'when first arg is not a string' do
40
- it 'raises ArgumentError' do
41
- expect{ subject.parse([1]) }.to raise_error(ArgumentError)
42
- end
43
- end
44
-
45
39
  end
46
40
 
47
41
  end
@@ -0,0 +1,89 @@
1
+ require_relative '../../../spec_helper.rb'
2
+
3
+ describe ListTool::App::ClearListCommand do
4
+ subject { ListTool::App::ClearListCommand }
5
+
6
+ describe '.match?' do
7
+ it 'returns true if "cl" or "clear-list" given' do
8
+ expect( subject.match? "cl" ).to be_truthy
9
+ expect( subject.match? "clear-list" ).to be_truthy
10
+ end
11
+
12
+ it 'returns false otherwise' do
13
+ expect( subject.match? "some-arg" ).to be_falsey
14
+ end
15
+ end
16
+
17
+
18
+ describe '.parse' do
19
+ it 'shifts 1 arg from ARGV' do
20
+ argv = ['2']
21
+ expect( argv ).to receive(:shift).with(no_args).and_return('2')
22
+ subject.parse argv
23
+ end
24
+
25
+ context 'success' do
26
+ it 'returns {list: list_num}' do
27
+ expect( subject.parse(['2']) ).to eq( {list: 1} )
28
+ end
29
+ end
30
+
31
+ context 'failure' do
32
+
33
+ context 'when list number not given' do
34
+ it 'raises ArgumentError' do
35
+ expect{ subject.parse[] }.to raise_error(ArgumentError)
36
+ end
37
+ end
38
+
39
+ context 'when list number is not a integer' do
40
+ it 'raises ArgumentError' do
41
+ expect{ subject.parse(["not_an_integer"]) }.to raise_error(ArgumentError)
42
+ end
43
+ end
44
+
45
+ context 'when list number is less than 1' do
46
+ it 'raises ArgumentError' do
47
+ expect{ subject.parse(['0']) }.to raise_error( ArgumentError )
48
+ end
49
+ end
50
+
51
+ context 'when not an array given' do
52
+ it 'raises ArgumentError' do
53
+ expect{ subject.parse "not_an_array" }.to raise_error( ArgumentError )
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+
62
+ describe '.execute' do
63
+ let (:lister) { ListTool::Lister.new }
64
+
65
+ context 'success' do
66
+ it 'calls lister.clear_list with given list number' do
67
+ expect(lister).to receive(:clear_list).with(2).and_return("not_nil")
68
+ subject.execute({list: 2}, lister)
69
+ end
70
+ end
71
+
72
+ context 'failure' do
73
+ context 'when list not found' do
74
+ it 'raises ListNotFoundError' do
75
+ expect{ subject.execute({list: -2}, lister) }.to raise_error(ListTool::ListNotFoundError )
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+
82
+
83
+ describe '.help' do
84
+ it 'returns help message' do
85
+ expect( subject.help ).to be_a String
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../../../spec_helper.rb'
2
+
3
+ describe ListTool::App::Command do
4
+ subject { ListTool::App::Command }
5
+
6
+ describe '::parse_number' do
7
+ context 'success' do
8
+ it "returns an integer" do
9
+ expect( subject.parse_number("2", "list") ).to eq 1
10
+ end
11
+ end
12
+
13
+ context 'failure' do
14
+
15
+ it 'injects given number name into error message' do
16
+ expect{ subject.parse_number("not_an_int", "smth") }.to raise_error(ArgumentError, /smth/)
17
+ end
18
+
19
+ context 'when list number is not a integer' do
20
+ it 'raises ArgumentError' do
21
+ expect{ subject.parse_number("not_an_int", "item") }.to raise_error(ArgumentError)
22
+ end
23
+ end
24
+
25
+ context 'when list number is less than 1' do
26
+ it 'raises ArgumentError' do
27
+ expect{ subject.parse_number("-1", "list") }.to raise_error( ArgumentError)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ describe '::parse_item_number' do
35
+ it 'calls ::parse_number with given string and "item"' do
36
+ expect(subject).to receive(:parse_number).with("2", "item")
37
+ subject.parse_item_number("2")
38
+ end
39
+ end
40
+
41
+ describe '::parse_item_number!' do
42
+ it 'calls ::parse_item_number with given string' do
43
+ expect(subject).to receive(:parse_item_number).with("2")
44
+ subject.parse_item_number!("2")
45
+ end
46
+
47
+ it 'raises ArgumentError if number == nil' do
48
+ expect{ subject.parse_item_number!(nil) }.to raise_error(ArgumentError, /item number/)
49
+ end
50
+ end
51
+
52
+
53
+ describe '::parse_list_number' do
54
+ it 'calls ::parse_number with given string and "list"' do
55
+ expect(subject).to receive(:parse_number).with("2", "list")
56
+ subject.parse_list_number("2")
57
+ end
58
+ end
59
+
60
+ describe '::parse_list_number!' do
61
+ it 'calls ::parse_list_number with given string' do
62
+ expect(subject).to receive(:parse_list_number).with("2")
63
+ subject.parse_list_number!("2")
64
+ end
65
+
66
+ it 'raises ArgumentError if number == nil' do
67
+ expect{ subject.parse_list_number!(nil) }.to raise_error(ArgumentError, /list number/)
68
+ end
69
+ end
70
+
71
+
72
+ describe '::ensure_existence_of' do
73
+ it 'raises error if given argument is nil' do
74
+ expect{ subject.ensure_existence_of("value" => nil) }.to raise_error(ArgumentError)
75
+ end
76
+
77
+ it 'raises error if any of given hash values is nil' do
78
+ expect{ subject.ensure_existence_of("value1" => "not_nil", "value2" => nil) }.to raise_error(ArgumentError)
79
+ end
80
+
81
+ it 'inserts key name to exception message' do
82
+ expect{ subject.ensure_existence_of("value1" => nil) }.to raise_error(ArgumentError, /value1/)
83
+ end
84
+ end
85
+
86
+
87
+ describe '::fail_if_not_an_array' do
88
+ context 'when argument is an array' do
89
+ it 'does nothing' do
90
+ expect{ subject.fail_if_not_an_array([]) }.not_to raise_error
91
+ end
92
+ end
93
+
94
+ context 'when argument is not an array' do
95
+ it 'raises ArgumentError' do
96
+ expect{ subject.fail_if_not_an_array("not_an_array") }.to raise_error(ArgumentError)
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -4,7 +4,7 @@ describe ListTool::App::Commands do
4
4
  subject { ListTool::App::Commands }
5
5
 
6
6
  it 'stores command list' do
7
- commands = ListTool::App.constants.map {|c| ListTool::App.const_get(c)} - [ListTool::App::Commands, ListTool::App::Printer, ListTool::App::Runner, ListTool::App::Colorizer]
7
+ commands = ListTool::App.constants.map {|c| ListTool::App.const_get(c)} - [ListTool::App::Commands, ListTool::App::Printer, ListTool::App::Runner, ListTool::App::Colorizer, ListTool::App::Command]
8
8
  expect(subject::COMMANDS).to eq commands
9
9
  end
10
10
 
@@ -67,6 +67,14 @@ describe ListTool::List do
67
67
  end
68
68
 
69
69
 
70
+ describe '#inspect' do
71
+ it "returns class name, object id, list name and array of item texts" do
72
+ str = "#<ListTool::List:0x#{list.__id__.to_s(16)}, name: Todolist, items: [item1, item2]>"
73
+ expect( list.inspect ).to eq str
74
+ end
75
+ end
76
+
77
+
70
78
  describe '#clear!' do
71
79
  it "clears items array" do
72
80
  list.clear!
@@ -51,6 +51,14 @@ describe ListTool::ListerData do
51
51
  end
52
52
 
53
53
 
54
+ describe '#inspect' do
55
+ it "returns class name, object id, array of list names and default list name" do
56
+ str = "#<ListTool::ListerData:0x#{data.__id__.to_s(16)}, lists: [Todolist, Wishlist], default_list: Todolist>"
57
+ expect( data.inspect ).to eq str
58
+ end
59
+ end
60
+
61
+
54
62
  describe '#add_list' do
55
63
 
56
64
  context 'hash given' do
@@ -72,35 +72,36 @@ describe ListTool::Lister do
72
72
 
73
73
  describe '#list' do
74
74
 
75
- context 'success' do
76
- context 'no options' do
77
- it 'returns hash with list name and array of item texts' do
78
- expect( lister.list(0) ).to eq( {name: 'Todolist', items: ['item1', 'item2']} )
79
- end
75
+ context 'no options' do
76
+ it 'returns hash with list name and array of item texts' do
77
+ expect( lister.list(0) ).to eq( {name: 'Todolist', items: ['item1', 'item2']} )
80
78
  end
79
+ end
81
80
 
82
- context 'list number not given' do
83
- it 'returns contents of default list' do
84
- expect( lister.list ).to eq( {name: 'Todolist', items: ['item1', 'item2']} )
85
- end
81
+ context 'list number not given' do
82
+ it 'returns contents of default list' do
83
+ expect( lister.list ).to eq( {name: 'Todolist', items: ['item1', 'item2']} )
86
84
  end
87
85
  end
88
86
 
89
- context 'failure' do
90
- context 'no list with given index' do
91
- it 'returns nil' do
92
- expect( lister.list(2) ).to be_nil
93
- end
94
- end
87
+ end
95
88
 
96
- context 'default list not set and list not given' do
97
- it 'raises NoDefaultListError' do
98
- lister = ListTool::Lister.new
99
- expect{ lister.list }.to raise_error(ListTool::NoDefaultListError)
100
- end
89
+
90
+ describe '#default_list' do
91
+ let(:data) { lister.instance_variable_get(:@data) }
92
+
93
+ context 'when default list is set' do
94
+ it 'returns hash with default ist name and array of item texts' do
95
+ expect( lister.default_list ).to eq( {name: 'Todolist', items: ['item1', 'item2']} )
101
96
  end
102
97
  end
103
98
 
99
+ context 'when default list is not set' do
100
+ it 'returns nil' do
101
+ allow( data ).to receive(:default_list).and_return(nil)
102
+ expect( lister.default_list ).to be_nil
103
+ end
104
+ end
104
105
  end
105
106
 
106
107
 
@@ -112,75 +113,88 @@ describe ListTool::Lister do
112
113
 
113
114
 
114
115
  describe '#method_missing' do
116
+ let(:data) { lister.instance_variable_get(:@data) }
115
117
 
116
- context 'success' do
117
-
118
- it 'returns self' do
119
- expect( lister.add_item('text') ).to eq lister
120
- end
121
-
122
- context '_list method given' do
123
- it 'deligates method call to @data' do
124
- data = lister.instance_variable_get(:@data)
125
- expect( data ).to receive(:add_list).with('new_list')
126
- lister.add_list('new_list')
127
- end
118
+ context 'method name ends with _list' do
119
+ it 'deligates method call to ListerData' do
120
+ expect(data).to receive(:add_list).with("name")
121
+ lister.add_list("name")
128
122
  end
123
+ end
129
124
 
130
- context '_item method given' do
125
+ context 'when method name ends with _item' do
126
+ context 'and list index is not specified' do
131
127
 
132
- context 'list number not specified' do
128
+ context 'if default list is set' do
133
129
  it 'deligates method call to default list' do
134
- default_list = lister.instance_variable_get(:@data).default_list
135
- expect( default_list ).to receive(:add_item).with('new_item')
130
+ list = data.default_list
131
+ expect(list).to receive(:add_item).with("text")
132
+ lister.add_item("text")
133
+ end
134
+ end
136
135
 
137
- lister.add_item('new_item')
136
+ context 'if default list is not set' do
137
+ it 'raises NoDefaultListError' do
138
+ allow( data ).to receive(:default_list).and_return(nil)
139
+ expect{ lister.add_item }.to raise_error(ListTool::NoDefaultListError)
138
140
  end
139
141
  end
140
142
 
141
- context 'list number specified' do
142
- it 'deligates method call to specified list' do
143
- list = lister.instance_variable_get(:@data).lists[0]
144
- expect( list ).to receive(:add_item).with('new_item')
143
+ end
145
144
 
146
- lister.add_item('new_item', list: 0)
145
+ context 'and list index is specified' do
146
+
147
+ context 'if list with given index exists' do
148
+ it 'deligates method call to list with given index' do
149
+ list = data.lists[1]
150
+ expect(list).to receive(:add_item).with("text")
151
+ lister.add_item("text", {list: 1})
152
+ end
153
+ end
154
+
155
+ context 'if there is no list with given index' do
156
+ it 'raises ListNotFoundError' do
157
+ expect{ lister.add_item("text", {list: 3}) }.to raise_error(ListTool::ListNotFoundError)
147
158
  end
148
159
  end
149
160
 
150
161
  end
162
+ end
151
163
 
164
+ context 'for any other methods' do
165
+ it 'raises NoMethodError' do
166
+ expect{ lister.unknown_method }.to raise_error(NoMethodError)
167
+ end
152
168
  end
153
169
 
154
- context 'failure' do
170
+ end
155
171
 
156
- context 'call to unknown method' do
157
- it 'raises NoMethodError' do
158
- message = "undefined method 'no_such_method' for #{lister.inspect}"
159
- expect{lister.no_such_method}.to raise_error(NoMethodError, message)
160
- end
161
- end
162
172
 
163
- context 'no list with specified number' do
164
- it 'returns nil' do
165
- expect( lister.add_item('new_item', list: 3) ).to be_nil
166
- end
173
+ describe '#get_list' do
174
+ context 'when list index given' do
175
+ it 'returns corresponding list object' do
176
+ list = lister.instance_variable_get(:@data).instance_variable_get(:@lists)[0]
177
+ expect( lister.send(:get_list, 0) ).to eq list
167
178
  end
179
+ end
180
+
181
+ context 'when list index not given' do
168
182
 
169
- context 'method returned nil' do
170
- it 'returns nil' do
171
- expect( lister.delete_item(3) ).to be_nil
183
+ context 'default list is set' do
184
+ it 'returns default list' do
185
+ list = lister.instance_variable_get(:@data).instance_variable_get(:@default_list)
186
+ expect( lister.send(:get_list) ).to eq list
172
187
  end
173
188
  end
174
189
 
175
- context 'list number not specified and default list not set' do
190
+ context 'default list is not set' do
176
191
  it 'raises NoDefaultListError' do
177
- lister = ListTool::Lister.new
178
- expect{ lister.add_item('new item') }.to raise_error(ListTool::NoDefaultListError)
192
+ allow( lister.instance_variable_get(:@data) ).to receive(:default_list).and_return(nil)
193
+ expect{ lister.send(:get_list) }.to raise_error(ListTool::NoDefaultListError)
179
194
  end
180
195
  end
181
-
196
+
182
197
  end
183
-
184
198
  end
185
199
 
186
200
  end