list-tool 1.0.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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/clt +12 -0
- data/lib/list_tool/app/commands/add_item_command.rb +39 -0
- data/lib/list_tool/app/commands/add_list_command.rb +30 -0
- data/lib/list_tool/app/commands/delete_item_command.rb +39 -0
- data/lib/list_tool/app/commands/delete_list_command.rb +32 -0
- data/lib/list_tool/app/commands/help_command.rb +24 -0
- data/lib/list_tool/app/commands/rename_list_command.rb +34 -0
- data/lib/list_tool/app/commands/replace_item_command.rb +34 -0
- data/lib/list_tool/app/commands/show_items_command.rb +35 -0
- data/lib/list_tool/app/commands/show_lists_command.rb +26 -0
- data/lib/list_tool/app/commands/unknown_command.rb +26 -0
- data/lib/list_tool/app/commands/use_command.rb +31 -0
- data/lib/list_tool/app/commands/version_command.rb +24 -0
- data/lib/list_tool/app/commands.rb +43 -0
- data/lib/list_tool/app/printer.rb +41 -0
- data/lib/list_tool/app/runner.rb +54 -0
- data/lib/list_tool/app/string.rb +9 -0
- data/lib/list_tool/app.rb +9 -0
- data/lib/list_tool/data.rb +75 -0
- data/lib/list_tool/file_manager.rb +27 -0
- data/lib/list_tool/item.rb +23 -0
- data/lib/list_tool/json_parser.rb +11 -0
- data/lib/list_tool/list.rb +88 -0
- data/lib/list_tool/lister.rb +81 -0
- data/lib/list_tool/version.rb +3 -0
- data/lib/list_tool.rb +19 -0
- data/list_tool.gemspec +31 -0
- data/spec/fixtures/data.json +18 -0
- data/spec/list_tool/app/commands/add_item_command_spec.rb +108 -0
- data/spec/list_tool/app/commands/add_list_command_spec.rb +74 -0
- data/spec/list_tool/app/commands/delete_item_command_spec.rb +116 -0
- data/spec/list_tool/app/commands/delete_list_command_spec.rb +89 -0
- data/spec/list_tool/app/commands/help_command_spec.rb +41 -0
- data/spec/list_tool/app/commands/rename_list_command_spec.rb +95 -0
- data/spec/list_tool/app/commands/replace_item_command_spec.rb +97 -0
- data/spec/list_tool/app/commands/show_items_command_spec.rb +111 -0
- data/spec/list_tool/app/commands/show_lists_command_spec.rb +48 -0
- data/spec/list_tool/app/commands/unknown_command_spec.rb +31 -0
- data/spec/list_tool/app/commands/use_command_spec.rb +79 -0
- data/spec/list_tool/app/commands/version_comand_spec.rb +41 -0
- data/spec/list_tool/app/commands_spec.rb +80 -0
- data/spec/list_tool/app/printer_spec.rb +54 -0
- data/spec/list_tool/app/runner_spec.rb +166 -0
- data/spec/list_tool/app/string_spec.rb +32 -0
- data/spec/list_tool/data_spec.rb +257 -0
- data/spec/list_tool/file_manager_spec.rb +84 -0
- data/spec/list_tool/item_spec.rb +42 -0
- data/spec/list_tool/json_parser_spec.rb +14 -0
- data/spec/list_tool/list_spec.rb +221 -0
- data/spec/list_tool/lister_spec.rb +186 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/factory.rb +33 -0
- 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,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
|
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,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
|