hammer_cli 0.0.9 → 0.0.10
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 +4 -4
- data/README.md +5 -5
- data/doc/creating_apipie_commands.md +296 -0
- data/doc/creating_commands.md +547 -0
- data/doc/developer_docs.md +5 -926
- data/doc/development_tips.md +30 -0
- data/doc/writing_a_plugin.md +90 -0
- data/lib/hammer_cli/abstract.rb +31 -11
- data/lib/hammer_cli/apipie/resource.rb +14 -6
- data/lib/hammer_cli/apipie/write_command.rb +14 -5
- data/lib/hammer_cli/exception_handler.rb +7 -4
- data/lib/hammer_cli/options/normalizers.rb +27 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +8 -8
- data/lib/hammer_cli/output/adapter/csv.rb +37 -4
- data/lib/hammer_cli/output/adapter/silent.rb +2 -2
- data/lib/hammer_cli/output/dsl.rb +3 -1
- data/lib/hammer_cli/output/output.rb +24 -19
- data/lib/hammer_cli/utils.rb +18 -0
- data/lib/hammer_cli/version.rb +1 -1
- data/lib/hammer_cli.rb +1 -0
- data/test/unit/abstract_test.rb +296 -0
- data/test/unit/apipie/command_test.rb +270 -0
- data/test/unit/apipie/fake_api.rb +101 -0
- data/test/unit/apipie/read_command_test.rb +34 -0
- data/test/unit/apipie/write_command_test.rb +38 -0
- data/test/unit/exception_handler_test.rb +45 -0
- data/test/unit/main_test.rb +47 -0
- data/test/unit/options/normalizers_test.rb +148 -0
- data/test/unit/options/option_definition_test.rb +43 -0
- data/test/unit/output/adapter/abstract_test.rb +96 -0
- data/test/unit/output/adapter/base_test.rb +27 -0
- data/test/unit/output/adapter/csv_test.rb +75 -0
- data/test/unit/output/adapter/table_test.rb +58 -0
- data/test/unit/output/definition_test.rb +27 -0
- data/test/unit/output/dsl_test.rb +119 -0
- data/test/unit/output/fields_test.rb +97 -0
- data/test/unit/output/formatters_test.rb +83 -0
- data/test/unit/output/output_test.rb +104 -0
- data/test/unit/settings_test.rb +106 -0
- data/test/unit/test_helper.rb +20 -0
- data/test/unit/utils_test.rb +35 -0
- data/test/unit/validator_test.rb +142 -0
- metadata +112 -35
- data/LICENSE +0 -5
- data/hammer_cli_complete +0 -13
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
|
4
|
+
class CustomFieldType
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe HammerCLI::Output::Dsl do
|
13
|
+
|
14
|
+
let(:dsl) { HammerCLI::Output::Dsl.new }
|
15
|
+
let(:field_type) { FieldType }
|
16
|
+
let(:first_field) { dsl.fields[0] }
|
17
|
+
let(:last_field) { dsl.fields[-1] }
|
18
|
+
|
19
|
+
it "should be empty after initialization" do
|
20
|
+
dsl.fields.length.must_equal 0
|
21
|
+
end
|
22
|
+
|
23
|
+
context "fields" do
|
24
|
+
it "should create DataField as default field type" do
|
25
|
+
dsl.build do
|
26
|
+
field :f, "F"
|
27
|
+
end
|
28
|
+
first_field.class.must_equal Fields::DataField
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create DataField of desired type" do
|
32
|
+
dsl.build do
|
33
|
+
field :f, "F", CustomFieldType
|
34
|
+
end
|
35
|
+
first_field.class.must_equal CustomFieldType
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should store all field details" do
|
39
|
+
dsl.build do
|
40
|
+
field :f, "F"
|
41
|
+
end
|
42
|
+
|
43
|
+
first_field.must_equal last_field
|
44
|
+
first_field.path.must_equal [:f]
|
45
|
+
first_field.label.must_equal "F"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "can define multiple fields" do
|
49
|
+
dsl.build do
|
50
|
+
field :name, "Name"
|
51
|
+
field :surname, "Surname"
|
52
|
+
field :email, "Email"
|
53
|
+
end
|
54
|
+
|
55
|
+
dsl.fields.length.must_equal 3
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "custom fields" do
|
60
|
+
|
61
|
+
let(:options) {{:a => 1, :b => 2}}
|
62
|
+
|
63
|
+
it "it creates field of a desired type" do
|
64
|
+
dsl.build do
|
65
|
+
custom_field CustomFieldType, :a => 1, :b => 2
|
66
|
+
end
|
67
|
+
first_field.class.must_equal CustomFieldType
|
68
|
+
end
|
69
|
+
|
70
|
+
it "passes all options to the field instance" do
|
71
|
+
dsl.build do
|
72
|
+
custom_field CustomFieldType, :a => 1, :b => 2
|
73
|
+
end
|
74
|
+
first_field.options.must_equal options
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
context "path definition" do
|
80
|
+
|
81
|
+
it "from appends to path" do
|
82
|
+
dsl.build do
|
83
|
+
from :key1 do
|
84
|
+
field :email, "Email"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
last_field.path.must_equal [:key1, :email]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "path can be nil to handle the parent structure" do
|
91
|
+
dsl.build do
|
92
|
+
from :key1 do
|
93
|
+
field nil, "Email"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
last_field.path.must_equal [:key1]
|
97
|
+
end
|
98
|
+
|
99
|
+
it "from can be nested" do
|
100
|
+
dsl.build do
|
101
|
+
from :key1 do
|
102
|
+
from :key2 do
|
103
|
+
from :key3 do
|
104
|
+
field :name, "Name"
|
105
|
+
end
|
106
|
+
field :email, "Email"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
first_field.path.must_equal [:key1, :key2, :key3, :name]
|
111
|
+
last_field.path.must_equal [:key1, :key2, :email]
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
end
|
119
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
|
4
|
+
describe Fields::Field do
|
5
|
+
|
6
|
+
let(:field) { Fields::Field.new }
|
7
|
+
|
8
|
+
describe "get_value" do
|
9
|
+
it "should exist" do
|
10
|
+
assert field.respond_to? :get_value
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should take data as a parameter" do
|
14
|
+
field.method(:get_value).arity.must_equal 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
describe Fields::LabeledField do
|
21
|
+
|
22
|
+
let(:label) { "Some Label" }
|
23
|
+
let(:field) { Fields::LabeledField.new :label => label }
|
24
|
+
|
25
|
+
context "labels" do
|
26
|
+
it "has label" do
|
27
|
+
assert field.respond_to? :label
|
28
|
+
end
|
29
|
+
|
30
|
+
it "is possible to set label in constructor" do
|
31
|
+
field.label.must_equal label
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe Fields::DataField do
|
38
|
+
|
39
|
+
let(:symbol_data) {{
|
40
|
+
:name => "John Doe",
|
41
|
+
:email => "john.doe@example.com",
|
42
|
+
:address => {
|
43
|
+
:city => {
|
44
|
+
:name => "New York",
|
45
|
+
:zip => "1234"
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}}
|
49
|
+
|
50
|
+
let(:string_data) {{
|
51
|
+
"name" => "Eric Doe",
|
52
|
+
"email" => "eric.doe@example.com",
|
53
|
+
"address" => {
|
54
|
+
"city" => {
|
55
|
+
"name" => "Boston",
|
56
|
+
"zip" => "6789"
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}}
|
60
|
+
|
61
|
+
let(:label) { "Some Label" }
|
62
|
+
let(:path) { [:address, :city, :name] }
|
63
|
+
let(:field) { Fields::DataField.new :label => label, :path => path }
|
64
|
+
|
65
|
+
it "stores label from constructor" do
|
66
|
+
field.label.must_equal label
|
67
|
+
end
|
68
|
+
|
69
|
+
it "stores path from constructor" do
|
70
|
+
field.path.must_equal path
|
71
|
+
end
|
72
|
+
|
73
|
+
it "default path should be empty array" do
|
74
|
+
Fields::DataField.new.path.must_equal []
|
75
|
+
end
|
76
|
+
|
77
|
+
context "getting data" do
|
78
|
+
|
79
|
+
it "should pick correct value" do
|
80
|
+
field.get_value(symbol_data).must_equal symbol_data[:address][:city][:name]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should pick correct value independent of key type" do
|
84
|
+
field.get_value(string_data).must_equal string_data["address"]["city"]["name"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should pick correct value even if data contains empty key (#3352)" do
|
88
|
+
string_data[''] = {}
|
89
|
+
field.get_value(string_data).must_equal string_data["address"]["city"]["name"]
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
describe HammerCLI::Output::Formatters::FormatterLibrary do
|
4
|
+
it "accepts formatter" do
|
5
|
+
lib = HammerCLI::Output::Formatters::FormatterLibrary.new(
|
6
|
+
:Id => HammerCLI::Output::Formatters::FieldFormatter.new)
|
7
|
+
lib.formatter_for_type(Fields::Id).must_be_instance_of HammerCLI::Output::Formatters::FormatterContainer
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can add formatter to instance" do
|
11
|
+
lib = HammerCLI::Output::Formatters::FormatterLibrary.new
|
12
|
+
lib.register_formatter :Id, HammerCLI::Output::Formatters::FieldFormatter.new
|
13
|
+
lib.formatter_for_type(Fields::Id).must_be_instance_of HammerCLI::Output::Formatters::FormatterContainer
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe HammerCLI::Output::Formatters::FieldFormatter do
|
18
|
+
let(:formatter) { HammerCLI::Output::Formatters::FieldFormatter.new }
|
19
|
+
it "has format method" do
|
20
|
+
formatter.respond_to?(:format).must_equal true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has tags" do
|
24
|
+
formatter.tags.must_be_kind_of Array
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should know if it has matching tags" do
|
28
|
+
formatter.stubs(:tags).returns([:tag])
|
29
|
+
formatter.match?([:tag]).must_equal true
|
30
|
+
formatter.match?([:notag]).must_equal false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe HammerCLI::Output::Formatters::FormatterContainer do
|
35
|
+
|
36
|
+
class TestFormatter
|
37
|
+
def format(data)
|
38
|
+
data+'.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it "accepts formatter" do
|
43
|
+
container = HammerCLI::Output::Formatters::FormatterContainer.new(TestFormatter.new)
|
44
|
+
container.format('').must_equal '.'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "has format method" do
|
48
|
+
container = HammerCLI::Output::Formatters::FormatterContainer.new
|
49
|
+
container.respond_to?(:format).must_equal true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "can add formatter to instance" do
|
53
|
+
container = HammerCLI::Output::Formatters::FormatterContainer.new(TestFormatter.new)
|
54
|
+
container.add_formatter TestFormatter.new
|
55
|
+
container.format('').must_equal '..'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe HammerCLI::Output::Formatters::ColorFormatter do
|
60
|
+
it "colorizes the value" do
|
61
|
+
formatter = HammerCLI::Output::Formatters::ColorFormatter.new(:red)
|
62
|
+
formatter.format('red').must_equal "\e[31mred\e[0m"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe HammerCLI::Output::Formatters::DateFormatter do
|
67
|
+
it "formats the date" do
|
68
|
+
formatter = HammerCLI::Output::Formatters::DateFormatter.new
|
69
|
+
formatter.format('2000-01-01 21:01:01').must_equal "2000/01/01 21:01:01"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns empty string on wrong value" do
|
73
|
+
formatter = HammerCLI::Output::Formatters::DateFormatter.new
|
74
|
+
formatter.format('wrong value').must_equal ""
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe HammerCLI::Output::Formatters::ListFormatter do
|
79
|
+
it "serializes the value" do
|
80
|
+
formatter = HammerCLI::Output::Formatters::ListFormatter.new
|
81
|
+
formatter.format([1, 2]).must_equal '1, 2'
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../test_helper')
|
2
|
+
|
3
|
+
describe HammerCLI::Output::Output do
|
4
|
+
|
5
|
+
let(:adapter) { HammerCLI::Output::Adapter::Silent }
|
6
|
+
let(:definition) { HammerCLI::Output::Definition.new }
|
7
|
+
|
8
|
+
let(:context) { { :adapter => :silent } }
|
9
|
+
let(:out_class) { HammerCLI::Output::Output }
|
10
|
+
let(:out) { out_class.new(context) }
|
11
|
+
|
12
|
+
context "messages" do
|
13
|
+
|
14
|
+
let(:msg) { "Some message" }
|
15
|
+
let(:details) { "Some\nmessage\ndetails" }
|
16
|
+
let(:msg_arg) { {:a => 'A'} }
|
17
|
+
|
18
|
+
it "prints info message via adapter" do
|
19
|
+
adapter.any_instance.expects(:print_message).with(msg, {})
|
20
|
+
out.print_message(msg)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "prints info message via adapter with arguments" do
|
24
|
+
adapter.any_instance.expects(:print_message).with(msg, msg_arg)
|
25
|
+
out.print_message(msg, msg_arg)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "prints error message via adapter" do
|
29
|
+
adapter.any_instance.expects(:print_error).with(msg, nil, {})
|
30
|
+
out.print_error(msg, nil)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "prints error message via adapter with arguments" do
|
34
|
+
adapter.any_instance.expects(:print_error).with(msg, nil, msg_arg)
|
35
|
+
out.print_error(msg, nil, msg_arg)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "prints error message with details via adapter" do
|
39
|
+
adapter.any_instance.expects(:print_error).with(msg, details, {})
|
40
|
+
out.print_error(msg, details)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "prints error message from exception via adapter" do
|
44
|
+
adapter.any_instance.expects(:print_error).with(msg, nil, {})
|
45
|
+
out.print_error(Exception.new(msg), nil)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "data" do
|
50
|
+
|
51
|
+
let(:item1) { {} }
|
52
|
+
let(:item2) { {} }
|
53
|
+
let(:collection) { [item1, item2] }
|
54
|
+
|
55
|
+
it "prints single resource" do
|
56
|
+
adapter.any_instance.expects(:print_records).with([], [{}])
|
57
|
+
out.print_records(definition, item1)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "prints array of resources" do
|
61
|
+
adapter.any_instance.expects(:print_records).with([], collection)
|
62
|
+
out.print_records(definition, collection)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
context "adapters" do
|
68
|
+
it "should register adapter" do
|
69
|
+
out_class.register_adapter(:test, HammerCLI::Output::Adapter::Silent)
|
70
|
+
out_class.adapters[:test].must_equal(HammerCLI::Output::Adapter::Silent)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return required default adapter" do
|
74
|
+
out = out_class.new({}, {:default_adapter => :silent})
|
75
|
+
out.adapter.must_be_instance_of HammerCLI::Output::Adapter::Silent
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should use adapter form context" do
|
79
|
+
out = out_class.new({:adapter => :silent})
|
80
|
+
out.adapter.must_be_instance_of HammerCLI::Output::Adapter::Silent
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should prioritize adapter from the context" do
|
84
|
+
out = out_class.new({:adapter => :table}, {:default_adapter => :silent})
|
85
|
+
out.adapter.must_be_instance_of HammerCLI::Output::Adapter::Table
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should use base adapter if the requested default was not found" do
|
89
|
+
out = out_class.new({}, {:default_adapter => :unknown})
|
90
|
+
out.adapter.must_be_instance_of HammerCLI::Output::Adapter::Base
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "formatters" do
|
95
|
+
it "should register formatter" do
|
96
|
+
formatter = HammerCLI::Output::Formatters::FieldFormatter.new
|
97
|
+
out_class.register_formatter(formatter, :type1, :type2)
|
98
|
+
out_class.formatters[:type1].must_equal([formatter])
|
99
|
+
out_class.formatters[:type2].must_equal([formatter])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
describe HammerCLI::Settings do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
# clean up global settings
|
7
|
+
HammerCLI::Settings.clear
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:settings) { HammerCLI::Settings }
|
11
|
+
|
12
|
+
it "returns nil when nothing is loaded" do
|
13
|
+
settings.get(:a).must_be_nil
|
14
|
+
settings.get(:a, :b).must_be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns nil on unknown key" do
|
18
|
+
settings.load({:a => 1})
|
19
|
+
settings.get(:b).must_be_nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns correct value" do
|
23
|
+
settings.load({:a => 1})
|
24
|
+
settings.get(:a).must_equal 1
|
25
|
+
end
|
26
|
+
|
27
|
+
it "takes both strings and symbols" do
|
28
|
+
settings.load({:a => 1, 'b' => 2})
|
29
|
+
settings.get('a').must_equal 1
|
30
|
+
settings.get(:b).must_equal 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it "finds nested settings" do
|
34
|
+
settings.load({:a => {:b => 1}})
|
35
|
+
settings.get(:a, :b).must_equal 1
|
36
|
+
settings.get(:a, 'b').must_equal 1
|
37
|
+
settings.get('a', :b).must_equal 1
|
38
|
+
end
|
39
|
+
|
40
|
+
it "loads all settings" do
|
41
|
+
settings.load({:a => 1, :b => 2})
|
42
|
+
settings.get(:a).must_equal 1
|
43
|
+
settings.get(:b).must_equal 2
|
44
|
+
end
|
45
|
+
|
46
|
+
it "merges settings on second load" do
|
47
|
+
settings.load({:a => 1, :b => 2, :d => {:e => 4, :f => 5}})
|
48
|
+
settings.load({:b => 'B', :c => 'C', :d => {:e => 'E'}})
|
49
|
+
settings.get(:a).must_equal 1
|
50
|
+
settings.get(:b).must_equal 'B'
|
51
|
+
settings.get(:c).must_equal 'C'
|
52
|
+
settings.get(:d, :e).must_equal 'E'
|
53
|
+
settings.get(:d, :f).must_equal 5
|
54
|
+
end
|
55
|
+
|
56
|
+
it "clear wipes all settings" do
|
57
|
+
settings.load({:a => 1, :b => 2})
|
58
|
+
settings.clear
|
59
|
+
settings.get(:a).must_be_nil
|
60
|
+
settings.get(:b).must_be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
context "load from file" do
|
64
|
+
|
65
|
+
let(:config1) do
|
66
|
+
config1 = Tempfile.new 'config'
|
67
|
+
config1 << ":host: 'https://localhost/'\n"
|
68
|
+
config1 << ":username: 'admin'\n"
|
69
|
+
config1.close
|
70
|
+
config1
|
71
|
+
end
|
72
|
+
|
73
|
+
let(:config2) do
|
74
|
+
config2 = Tempfile.new 'config2'
|
75
|
+
config2 << ":host: 'https://localhost.localdomain/'\n"
|
76
|
+
config2.close
|
77
|
+
config2
|
78
|
+
end
|
79
|
+
|
80
|
+
let(:config_without_creds) do
|
81
|
+
config_without_creds = Tempfile.new('config_without_creds')
|
82
|
+
config_without_creds << ":host: 'https://localhost.localdomain/'\n"
|
83
|
+
config_without_creds.close
|
84
|
+
config_without_creds
|
85
|
+
end
|
86
|
+
|
87
|
+
it "loads settings from file" do
|
88
|
+
settings.load_from_file [config2.path, config1.path]
|
89
|
+
settings.get(:host).must_equal 'https://localhost.localdomain/'
|
90
|
+
settings.get(:username).must_equal 'admin'
|
91
|
+
end
|
92
|
+
|
93
|
+
it "clears path history on clear invokation" do
|
94
|
+
settings.load_from_file [config2.path]
|
95
|
+
settings.clear
|
96
|
+
settings.path_history.must_equal []
|
97
|
+
end
|
98
|
+
|
99
|
+
it "store config path history" do
|
100
|
+
settings.load_from_file [config2.path, config1.path]
|
101
|
+
settings.path_history.must_equal [config1.path, config2.path]
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
SimpleCov.use_merging true
|
5
|
+
SimpleCov.start do
|
6
|
+
command_name 'MiniTest'
|
7
|
+
add_filter 'test'
|
8
|
+
end
|
9
|
+
SimpleCov.root Pathname.new(File.dirname(__FILE__) + "../../../")
|
10
|
+
|
11
|
+
|
12
|
+
require 'minitest/autorun'
|
13
|
+
require 'minitest/spec'
|
14
|
+
require "minitest-spec-context"
|
15
|
+
require "mocha/setup"
|
16
|
+
|
17
|
+
require 'hammer_cli'
|
18
|
+
|
19
|
+
Logging.logger.root.appenders = Logging::Appenders['__test__'] || Logging::Appenders::StringIo.new('__test__')
|
20
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
|
4
|
+
describe String do
|
5
|
+
|
6
|
+
context "formatting" do
|
7
|
+
|
8
|
+
let(:str) { "AA%<a>s BB%<b>s" }
|
9
|
+
let(:curly_str) { "AA%{a}s BB%{b}s" }
|
10
|
+
let(:pos_str) { "AA%s BB%s" }
|
11
|
+
|
12
|
+
it "should not fail without expected parameters" do
|
13
|
+
str.format({}).must_equal 'AA BB'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should replace positional parameters" do
|
17
|
+
pos_str.format(['A', 'B']).must_equal 'AAA BBB'
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should replace named parameters" do
|
21
|
+
str.format(:a => 'A', :b => 'B').must_equal 'AAA BBB'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should replace named parameters with string keys" do
|
25
|
+
str.format('a' => 'A', 'b' => 'B').must_equal 'AAA BBB'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should replace named parameters marked with curly brackets" do
|
29
|
+
curly_str.format(:a => 'A', :b => 'B').must_equal 'AAA BBB'
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
|
4
|
+
# describe HammerCLI::OptionValidator do
|
5
|
+
|
6
|
+
|
7
|
+
# end
|
8
|
+
|
9
|
+
describe "constraints" do
|
10
|
+
|
11
|
+
class FakeCmd < Clamp::Command
|
12
|
+
def initialize
|
13
|
+
super("")
|
14
|
+
@option_a = 1
|
15
|
+
@option_b = 1
|
16
|
+
@option_c = 1
|
17
|
+
@option_d = nil
|
18
|
+
@option_e = nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:cmd) {
|
23
|
+
FakeCmd.new
|
24
|
+
}
|
25
|
+
|
26
|
+
let(:option_names) { ["a", "b", "c", "d", "e"] }
|
27
|
+
let(:options_def) {
|
28
|
+
option_names.collect{ |n| Clamp::Option::Definition.new(["-"+n, "--option-"+n], n.upcase, "Option "+n.upcase) }
|
29
|
+
}
|
30
|
+
let(:options) { options_def.collect{|d| d.of(cmd) } }
|
31
|
+
|
32
|
+
describe HammerCLI::Validator::BaseConstraint do
|
33
|
+
|
34
|
+
let(:cls) { HammerCLI::Validator::BaseConstraint }
|
35
|
+
|
36
|
+
describe "exist?" do
|
37
|
+
it "throws not implemented error" do
|
38
|
+
constraint = cls.new(options, [:option_a, :option_b, :option_c])
|
39
|
+
proc{ constraint.exist? }.must_raise NotImplementedError
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "rejected" do
|
44
|
+
it "should raise exception when exist? returns true" do
|
45
|
+
constraint = cls.new(options, [])
|
46
|
+
constraint.stubs(:exist?).returns(true)
|
47
|
+
proc{ constraint.rejected }.must_raise HammerCLI::Validator::ValidationError
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise exception with a message" do
|
51
|
+
constraint = cls.new(options, [])
|
52
|
+
constraint.stubs(:exist?).returns(true)
|
53
|
+
begin
|
54
|
+
constraint.rejected :msg => "CUSTOM MESSAGE"
|
55
|
+
rescue HammerCLI::Validator::ValidationError => e
|
56
|
+
e.message.must_equal "CUSTOM MESSAGE"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should return nil when exist? returns true" do
|
61
|
+
constraint = cls.new(options, [])
|
62
|
+
constraint.stubs(:exist?).returns(false)
|
63
|
+
constraint.rejected.must_equal nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "required" do
|
68
|
+
it "should raise exception when exist? returns true" do
|
69
|
+
constraint = cls.new(options, [])
|
70
|
+
constraint.stubs(:exist?).returns(false)
|
71
|
+
proc{ constraint.required }.must_raise HammerCLI::Validator::ValidationError
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should raise exception with a message" do
|
75
|
+
constraint = cls.new(options, [])
|
76
|
+
constraint.stubs(:exist?).returns(false)
|
77
|
+
begin
|
78
|
+
constraint.rejected :msg => "CUSTOM MESSAGE"
|
79
|
+
rescue HammerCLI::Validator::ValidationError => e
|
80
|
+
e.message.must_equal "CUSTOM MESSAGE"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return nil when exist? returns true" do
|
85
|
+
constraint = cls.new(options, [])
|
86
|
+
constraint.stubs(:exist?).returns(true)
|
87
|
+
constraint.required.must_equal nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
describe HammerCLI::Validator::AllConstraint do
|
94
|
+
|
95
|
+
let(:cls) { HammerCLI::Validator::AllConstraint }
|
96
|
+
|
97
|
+
describe "exist?" do
|
98
|
+
|
99
|
+
it "should return true when no options are passed" do
|
100
|
+
constraint = cls.new(options, [])
|
101
|
+
constraint.exist?.must_equal true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return true when all the options exist" do
|
105
|
+
constraint = cls.new(options, [:option_a, :option_b, :option_c])
|
106
|
+
constraint.exist?.must_equal true
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should return false when one of the options is missing" do
|
110
|
+
constraint = cls.new(options, [:option_a, :option_b, :option_c, :option_d])
|
111
|
+
constraint.exist?.must_equal false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
describe HammerCLI::Validator::AnyConstraint do
|
118
|
+
|
119
|
+
let(:cls) { HammerCLI::Validator::AnyConstraint }
|
120
|
+
|
121
|
+
describe "exist?" do
|
122
|
+
|
123
|
+
it "should return true when no options are passed" do
|
124
|
+
constraint = cls.new(options, [])
|
125
|
+
constraint.exist?.must_equal true
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should return true when one of the options exist" do
|
129
|
+
constraint = cls.new(options, [:option_a, :option_d, :option_e])
|
130
|
+
constraint.exist?.must_equal true
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should return false when all the options are missing" do
|
134
|
+
constraint = cls.new(options, [:option_d, :option_e])
|
135
|
+
constraint.exist?.must_equal false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
end
|