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