list-tool 1.0.3 → 1.0.5

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