list-tool 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +1 -0
  9. data/bin/clt +12 -0
  10. data/lib/list_tool/app/commands/add_item_command.rb +39 -0
  11. data/lib/list_tool/app/commands/add_list_command.rb +30 -0
  12. data/lib/list_tool/app/commands/delete_item_command.rb +39 -0
  13. data/lib/list_tool/app/commands/delete_list_command.rb +32 -0
  14. data/lib/list_tool/app/commands/help_command.rb +24 -0
  15. data/lib/list_tool/app/commands/rename_list_command.rb +34 -0
  16. data/lib/list_tool/app/commands/replace_item_command.rb +34 -0
  17. data/lib/list_tool/app/commands/show_items_command.rb +35 -0
  18. data/lib/list_tool/app/commands/show_lists_command.rb +26 -0
  19. data/lib/list_tool/app/commands/unknown_command.rb +26 -0
  20. data/lib/list_tool/app/commands/use_command.rb +31 -0
  21. data/lib/list_tool/app/commands/version_command.rb +24 -0
  22. data/lib/list_tool/app/commands.rb +43 -0
  23. data/lib/list_tool/app/printer.rb +41 -0
  24. data/lib/list_tool/app/runner.rb +54 -0
  25. data/lib/list_tool/app/string.rb +9 -0
  26. data/lib/list_tool/app.rb +9 -0
  27. data/lib/list_tool/data.rb +75 -0
  28. data/lib/list_tool/file_manager.rb +27 -0
  29. data/lib/list_tool/item.rb +23 -0
  30. data/lib/list_tool/json_parser.rb +11 -0
  31. data/lib/list_tool/list.rb +88 -0
  32. data/lib/list_tool/lister.rb +81 -0
  33. data/lib/list_tool/version.rb +3 -0
  34. data/lib/list_tool.rb +19 -0
  35. data/list_tool.gemspec +31 -0
  36. data/spec/fixtures/data.json +18 -0
  37. data/spec/list_tool/app/commands/add_item_command_spec.rb +108 -0
  38. data/spec/list_tool/app/commands/add_list_command_spec.rb +74 -0
  39. data/spec/list_tool/app/commands/delete_item_command_spec.rb +116 -0
  40. data/spec/list_tool/app/commands/delete_list_command_spec.rb +89 -0
  41. data/spec/list_tool/app/commands/help_command_spec.rb +41 -0
  42. data/spec/list_tool/app/commands/rename_list_command_spec.rb +95 -0
  43. data/spec/list_tool/app/commands/replace_item_command_spec.rb +97 -0
  44. data/spec/list_tool/app/commands/show_items_command_spec.rb +111 -0
  45. data/spec/list_tool/app/commands/show_lists_command_spec.rb +48 -0
  46. data/spec/list_tool/app/commands/unknown_command_spec.rb +31 -0
  47. data/spec/list_tool/app/commands/use_command_spec.rb +79 -0
  48. data/spec/list_tool/app/commands/version_comand_spec.rb +41 -0
  49. data/spec/list_tool/app/commands_spec.rb +80 -0
  50. data/spec/list_tool/app/printer_spec.rb +54 -0
  51. data/spec/list_tool/app/runner_spec.rb +166 -0
  52. data/spec/list_tool/app/string_spec.rb +32 -0
  53. data/spec/list_tool/data_spec.rb +257 -0
  54. data/spec/list_tool/file_manager_spec.rb +84 -0
  55. data/spec/list_tool/item_spec.rb +42 -0
  56. data/spec/list_tool/json_parser_spec.rb +14 -0
  57. data/spec/list_tool/list_spec.rb +221 -0
  58. data/spec/list_tool/lister_spec.rb +186 -0
  59. data/spec/spec_helper.rb +18 -0
  60. data/spec/support/factory.rb +33 -0
  61. metadata +213 -0
@@ -0,0 +1,75 @@
1
+ module ListTool
2
+
3
+ class Data
4
+ include Enumerable
5
+
6
+ attr_reader :lists, :default_list
7
+
8
+ def initialize(hash = {})
9
+ raise ArgumentError, 'argument is not a hash' unless hash.respond_to?(:to_hash)
10
+
11
+ hash['lists'] ||= []
12
+ raise ArgumentError, 'incorrect data given' unless hash['lists'].respond_to?(:to_ary)
13
+
14
+ @lists = []
15
+ hash['lists'].each { |list_data| add_list(list_data) }
16
+
17
+ set_default_list(hash['default']) if hash['default']
18
+ end
19
+
20
+ def each
21
+ @lists.each { |list| yield(list) }
22
+ end
23
+
24
+ def add_list(data)
25
+ list = List.new(data)
26
+ @lists << list
27
+ list
28
+ end
29
+
30
+ def delete_list(index)
31
+ list = @lists.delete_at(index)
32
+ @default_list = nil if @default_list == list
33
+ list
34
+ end
35
+
36
+ def clear_list(index)
37
+ return nil if @lists[index] == nil
38
+ @lists[index].clear!
39
+ end
40
+
41
+ def rename_list(index, name)
42
+ return nil if @lists[index] == nil
43
+ @lists[index].rename(name)
44
+ end
45
+
46
+ def set_default_list(index)
47
+ raise ArgumentError, 'argument is not an integer' unless index.respond_to?(:to_int)
48
+ return nil if @lists[index] == nil
49
+ @default_list = @lists[index]
50
+ end
51
+
52
+ def move_list(index, direction)
53
+ case direction
54
+ when :up
55
+ return unless (1...@lists.length).include?(index)
56
+ @lists[index], @lists[index-1] = @lists[index-1], @lists[index]
57
+ when :down
58
+ return unless (0...(@lists.length-1)).include?(index)
59
+ @lists[index], @lists[index+1] = @lists[index+1], @lists[index]
60
+ end
61
+ end
62
+
63
+ def to_json
64
+ json = "{"
65
+ json += "\"default\":#{@lists.index(@default_list)}," if @default_list
66
+ json += "\"lists\":["
67
+ @lists.each do |list|
68
+ json += list.to_json
69
+ json += ',' unless list == @lists.last
70
+ end
71
+ json += ']}'
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ module ListTool
2
+
3
+ class FileManager
4
+
5
+ def self.load filename
6
+ File.read(filename)
7
+ rescue Errno::EACCES
8
+ raise FileAccessError, "can't read file '#{filename}': access denied"
9
+ rescue Errno::ENOENT
10
+ raise FileNotFoundError, "can't read file '#{filename}': file not found"
11
+ rescue
12
+ raise IOError, "can't read file '#{filename}': unknown error"
13
+ end
14
+
15
+ def self.save filename, data
16
+ File.open(filename, 'w') { |f| f << data.to_json }
17
+ rescue Errno::EACCES
18
+ raise FileAccessError, "can't open file '#{filename}': access denied"
19
+ rescue Errno::ENOENT
20
+ raise FileNotFoundError, "can't open file '#{filename}': file not found"
21
+ rescue
22
+ raise IOError, "can't open file '#{filename}': unknown error"
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,23 @@
1
+ module ListTool
2
+
3
+ class Item
4
+ attr_accessor :text
5
+
6
+ def initialize arg
7
+ if arg.is_a?(String)
8
+ @text = arg
9
+ elsif arg.is_a?(Hash)
10
+ raise(ArgumentError, "item text not found in given hash") unless arg['text'].is_a?(String)
11
+ @text = arg["text"]
12
+ else
13
+ raise(ArgumentError, "argument expected to be Hash or String, #{arg.class} given")
14
+ end
15
+ end
16
+
17
+ def to_json
18
+ "{\"text\":\"#{@text}\"}"
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,11 @@
1
+ module ListTool
2
+
3
+ class JsonParser
4
+
5
+ def self.parse json
6
+ JSON.parse(json)
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,88 @@
1
+ module ListTool
2
+
3
+ class List
4
+ include Enumerable
5
+
6
+ attr_reader :name, :items
7
+
8
+ def initialize(arg=nil)
9
+ if arg.respond_to?(:to_str)
10
+ @name = arg
11
+ @items = []
12
+ elsif arg.is_a?(Hash)
13
+ prepare_data(arg)
14
+
15
+ @name = arg['name']
16
+
17
+ @items = []
18
+ arg['items'].each do |item|
19
+ add_item(item)
20
+ end
21
+ else
22
+ raise(ArgumentError, "argument expected to be Hash or String, #{arg.class} given")
23
+ end
24
+ end
25
+
26
+ def clear!
27
+ @items = []
28
+ end
29
+
30
+ def rename str
31
+ raise ArgumentError, 'string expected' unless str.is_a?(String)
32
+ old_name = @name
33
+ @name = str
34
+ old_name
35
+ end
36
+
37
+ def to_json
38
+ json = "{\"name\":\"#{@name}\",\"items\":["
39
+ @items.each do |item|
40
+ json += item.to_json
41
+ json += ',' unless item == @items.last
42
+ end
43
+ json += ']}'
44
+ end
45
+
46
+ def each
47
+ @items.each { |item| yield(item) }
48
+ end
49
+
50
+ def add_item text
51
+ @items << Item.new(text)
52
+ end
53
+
54
+ def delete_item num
55
+ @items.delete_at(num)
56
+ end
57
+
58
+ def change_item index, new_text
59
+ raise ArgumentError, 'index is not an integer' unless index.respond_to?(:to_int)
60
+ raise ArgumentError, 'new text is not a string' unless new_text.respond_to?(:to_str)
61
+ return nil if @items[index].nil?
62
+ @items[index].text = new_text
63
+ end
64
+
65
+ def move_item num, direction
66
+ case direction
67
+ when :up
68
+ return unless (1...@items.length).include?(num)
69
+ @items[num], @items[num-1] = @items[num-1], @items[num]
70
+ when :down
71
+ return unless (0...(@items.length-1)).include?(num)
72
+ @items[num], @items[num+1] = @items[num+1], @items[num]
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def prepare_data data
79
+ data['items'] ||= []
80
+ data['name'] ||= 'Anonimous list'
81
+
82
+ data['name'].respond_to?(:to_str) || raise(ArgumentError, 'name is not a string')
83
+ data['items'].is_a?(Array) || raise(ArgumentError, '"items" is not an array')
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,81 @@
1
+ module ListTool
2
+ class Lister
3
+
4
+ def initialize
5
+ @data = Data.new
6
+ end
7
+
8
+ def inspect
9
+ "#<#{self.class}:0x#{self.__id__.to_s(16)}>"
10
+ end
11
+
12
+ def self.from_hash(hash)
13
+ lister = Lister.new
14
+ lister.instance_variable_set(:@data, Data.new(hash))
15
+ lister
16
+ end
17
+
18
+ def self.from_json(json)
19
+ data = JsonParser.parse(json)
20
+ from_hash(data)
21
+ end
22
+
23
+ def load(filename)
24
+ json = FileManager.load(filename)
25
+ @data = Data.new( JsonParser.parse(json) )
26
+ self
27
+ end
28
+
29
+ def save(filename)
30
+ FileManager.save(filename, @data)
31
+ end
32
+
33
+ def lists
34
+ out = {}
35
+ @data.each do |list|
36
+ out[list.name] = list.items.count
37
+ end
38
+ out
39
+ end
40
+
41
+ def list(index=nil)
42
+ list = if index
43
+ return nil if @data.lists[index].nil?
44
+ @data.lists[index]
45
+ else
46
+ raise NoDefaultListError, "default list not set" if @data.default_list.nil?
47
+ @data.default_list
48
+ end
49
+
50
+ out = {name: list.name, items: []}
51
+ list.items.each do |item|
52
+ out[:items] << item.text
53
+ end
54
+ out
55
+ end
56
+
57
+ def method_missing(name, *args, &block)
58
+ if name =~ /_list$/
59
+ object = @data
60
+ elsif name =~ /_item$/
61
+ object = if args[-1].is_a?(Hash) && args[-1].has_key?(:list)
62
+ return nil if @data.lists[ args[-1][:list] ].nil?
63
+ index = args.pop()[:list]
64
+ @data.lists[index]
65
+ else
66
+ raise NoDefaultListError, "default list not set" if @data.default_list.nil?
67
+ @data.default_list
68
+ end
69
+ else
70
+ super
71
+ end
72
+
73
+ result = object.send(name, *args, &block)
74
+ return nil if result.nil?
75
+ self
76
+ rescue NoMethodError => e
77
+ raise NoMethodError, "undefined method '#{name.to_s}' for #{self.inspect}"
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ module ListTool
2
+ VERSION = "1.0.0"
3
+ end
data/lib/list_tool.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'json'
2
+
3
+ require_relative "./list_tool/version"
4
+ require_relative "./list_tool/lister"
5
+ require_relative "./list_tool/item"
6
+ require_relative "./list_tool/list"
7
+ require_relative "./list_tool/data"
8
+ require_relative "./list_tool/json_parser"
9
+ require_relative "./list_tool/file_manager"
10
+ require_relative "./list_tool/app.rb"
11
+
12
+ module ListTool
13
+ class FileAccessError < StandardError; end
14
+ class FileNotFoundError < StandardError; end
15
+ class NoDefaultListError < StandardError; end
16
+ class ListNotFoundError < StandardError; end;
17
+ class ItemNotFoundError < StandardError; end;
18
+ class UnknownCommandError < StandardError; end;
19
+ end
data/list_tool.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'list_tool/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "list-tool"
8
+ spec.version = ListTool::VERSION
9
+ spec.date = '2014-06-08'
10
+ spec.authors = ["Dmitrii Krasnov"]
11
+ spec.email = ["vizvamitra@gmail.com"]
12
+ spec.summary = "list-tool-#{ListTool::VERSION}"
13
+ spec.description = "A tool to manage lists of strings (like todos) in your app or terminal"
14
+ spec.homepage = "http://github.com/vizvamitra/list-tool"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files`.split($/)
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.required_ruby_version = '>= 1.9.3'
23
+
24
+ # spec.add_runtime_dependency "json", '~> 1.8'
25
+ spec.add_development_dependency "bundler", "~> 1.5"
26
+ spec.add_development_dependency "rake", "~> 10.3"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "guard", "~> 2.6"
29
+ spec.add_development_dependency "guard-rspec", "~> 4.2"
30
+ spec.add_development_dependency "rb-readline", "~> 0.5"
31
+ end
@@ -0,0 +1,18 @@
1
+ { "default":0,
2
+ "lists":[
3
+ {
4
+ "name":"Todolist",
5
+ "items":[
6
+ {
7
+ "text": "item1"
8
+ },
9
+ {
10
+ "text": "item2"
11
+ }
12
+ ]
13
+ },
14
+ {
15
+ "name":"Wishlist",
16
+ "items":[]
17
+ }
18
+ ]}
@@ -0,0 +1,108 @@
1
+ require_relative '../../../spec_helper.rb'
2
+
3
+ describe ListTool::App::AddItemCommand do
4
+ subject { ListTool::App::AddItemCommand }
5
+
6
+ describe '.match?' do
7
+ it 'returns true if "a" or "add-item" given' do
8
+ expect( subject.match? "a" ).to be_truthy
9
+ expect( subject.match? "add-item" ).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
+
20
+ it 'shifts 2 args from ARGV' do
21
+ argv = ['text', '1']
22
+ expect( argv ).to receive(:shift).with(2).and_return(['text', '1'])
23
+ subject.parse argv
24
+ end
25
+
26
+ context 'success' do
27
+
28
+ context 'when list number not given' do
29
+ it 'returns {text: "item text"}' do
30
+ argv = ['item_text']
31
+ expect( subject.parse argv ).to eq( {text: 'item_text'} )
32
+ end
33
+ end
34
+
35
+ context 'when list number given' do
36
+ it 'returns {text: "item text", list: list_num}' do
37
+ argv = ['item_text', "2"]
38
+ expect( subject.parse argv ).to eq( {text: 'item_text', list: 1} )
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ context 'failure' do
45
+
46
+ context 'when item text not given' do
47
+ it 'raises ArgumentError' do
48
+ expect{ subject.parse([]) }.to raise_error( ArgumentError )
49
+ end
50
+ end
51
+
52
+ context 'when list number is not an integer' do
53
+ it 'raises ArgumentError' do
54
+ expect{ subject.parse(['text', 'not_an_int']) }.to raise_error( ArgumentError )
55
+ end
56
+ end
57
+
58
+ context 'when list number is less than 1' do
59
+ it 'raises ArgumentError' do
60
+ expect{ subject.parse(['text', '0']) }.to raise_error( ArgumentError )
61
+ end
62
+ end
63
+
64
+ context 'when not an array given' do
65
+ it 'raises ArgumentError' do
66
+ expect{ subject.parse "not_an_array" }.to raise_error( ArgumentError )
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+
74
+ describe '.execute' do
75
+ let (:lister) { ListTool::Lister.new }
76
+
77
+ context 'success' do
78
+ it 'calls lister.add_item with given options' do
79
+ expect(lister).to receive(:add_item).with('item text').and_return("not_nil")
80
+ subject.execute({text: 'item text'}, lister)
81
+ end
82
+ end
83
+
84
+ context 'failure' do
85
+
86
+ context 'when list not found' do
87
+ it 'raises ListNotFoundError' do
88
+ expect{ subject.execute({text: 'item text', list: 2}, lister) }.to raise_error(ListTool::ListNotFoundError )
89
+ end
90
+ end
91
+
92
+ context 'when list not specified and no default list set' do
93
+ it 'raises NoDefaultListError' do
94
+ expect{ subject.execute({text: 'item text'}, lister) }.to raise_error(ListTool::NoDefaultListError )
95
+ end
96
+ end
97
+
98
+ end
99
+ end
100
+
101
+
102
+ describe '.help' do
103
+ it 'returns help message' do
104
+ expect( subject.help ).to be_a String
105
+ end
106
+ end
107
+
108
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../../../spec_helper.rb'
2
+
3
+ describe ListTool::App::AddListCommand do
4
+ subject { ListTool::App::AddListCommand }
5
+
6
+ describe '.match?' do
7
+ it 'returns true if "al" or "add-list" given' do
8
+ expect( subject.match? "al" ).to be_truthy
9
+ expect( subject.match? "add-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 = ['name']
21
+ expect( argv ).to receive(:shift).with(no_args).and_return('name')
22
+ subject.parse argv
23
+ end
24
+
25
+ context 'success' do
26
+ it 'returns {name: "name"}' do
27
+ expect( subject.parse(['name']) ).to eq( {name: 'name'} )
28
+ end
29
+ end
30
+
31
+ context 'failure' do
32
+
33
+ context 'when new name not given' do
34
+ it 'raises ArgumentError' do
35
+ expect{ subject.parse[] }.to raise_error(ArgumentError)
36
+ end
37
+ end
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
+ end
46
+
47
+ end
48
+
49
+
50
+ describe '.execute' do
51
+ let (:lister) { double('lister') }
52
+
53
+ context 'success' do
54
+ it 'calls lister.add_list with given name' do
55
+ expect(lister).to receive(:add_list).with('list name').and_return("not_nil")
56
+ subject.execute({name: 'list name'}, lister)
57
+ end
58
+ end
59
+
60
+ context 'list creation failed' do
61
+ it 'raises RuntimeError' do
62
+ allow(lister).to receive(:add_list).and_return(nil)
63
+ expect{ subject.execute({name: 'some name'}, lister) }.to raise_error(RuntimeError)
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ describe '.help' do
70
+ it 'returns help message' do
71
+ expect( subject.help ).to be_a String
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,116 @@
1
+ require_relative '../../../spec_helper.rb'
2
+
3
+ describe ListTool::App::DeleteItemCommand do
4
+ subject { ListTool::App::DeleteItemCommand }
5
+
6
+ describe '.match?' do
7
+ it 'returns true if "d" or "del-item" given' do
8
+ expect( subject.match? "d" ).to be_truthy
9
+ expect( subject.match? "del-item" ).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
+
20
+ it 'shifts 2 args from ARGV' do
21
+ argv = ['2', '1']
22
+ expect( argv ).to receive(:shift).with(2).and_return(['2', '1'])
23
+ subject.parse argv
24
+ end
25
+
26
+ context 'success' do
27
+
28
+ context 'when list number not given' do
29
+ it 'returns {item: item_num}' do
30
+ argv = ["2"]
31
+ expect( subject.parse argv ).to eq( {item: 1} )
32
+ end
33
+ end
34
+
35
+ context 'when list number given' do
36
+ it 'returns {text: "item text", list: list_num}' do
37
+ argv = ["2", "1"]
38
+ expect( subject.parse argv ).to eq( {item: 1, list: 0} )
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ context 'failure' do
45
+
46
+ context 'when item number not given' do
47
+ it 'raises ArgumentError' do
48
+ expect{ subject.parse([]) }.to raise_error( ArgumentError )
49
+ end
50
+ end
51
+
52
+ context 'when list number is not an integer' do
53
+ it 'raises ArgumentError' do
54
+ expect{ subject.parse(['2', 'not_an_int']) }.to raise_error( ArgumentError )
55
+ end
56
+ end
57
+
58
+ context 'when list number is less than 1' do
59
+ it 'raises ArgumentError' do
60
+ expect{ subject.parse(['2', '0']) }.to raise_error( ArgumentError )
61
+ end
62
+ end
63
+
64
+ context 'when not an array given' do
65
+ it 'raises ArgumentError' do
66
+ expect{ subject.parse "not_an_array" }.to raise_error( ArgumentError )
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+
73
+
74
+ describe '.execute' do
75
+ let(:lister) { ListTool::Lister.new }
76
+
77
+ context 'success' do
78
+ context 'when list number is given' do
79
+ it 'calls lister.delete_item with item_num, {list: list_num}' do
80
+ expect(lister).to receive(:delete_item).with(2, {list: 2}).and_return("not_nill")
81
+ subject.execute({item: 2, list: 2}, lister)
82
+ end
83
+ end
84
+
85
+ context 'when list number is not given' do
86
+ it 'calls lister.delete_item with no args' do
87
+ expect(lister).to receive(:delete_item).with(2).and_return("not_nill")
88
+ subject.execute({item: 2}, lister)
89
+ end
90
+ end
91
+ end
92
+
93
+ context 'failure' do
94
+ context 'when list not found' do
95
+ it 'raises ListNotFoundError' do
96
+ expect{ subject.execute({item: 2, list: 2}, lister) }.to raise_error(ListTool::ListNotFoundError )
97
+ end
98
+ end
99
+
100
+ context 'when list not specified and no default list set' do
101
+ it 'raises NoDefaultListError' do
102
+ expect{ subject.execute({item: 2}, lister) }.to raise_error(ListTool::NoDefaultListError )
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+
110
+ describe '.help' do
111
+ it 'returns help message' do
112
+ expect( subject.help ).to be_a String
113
+ end
114
+ end
115
+
116
+ end