hammer_cli 0.0.18 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -314
  3. data/bin/hammer +45 -6
  4. data/config/cli.modules.d/module_config_template.yml +4 -0
  5. data/config/cli_config.template.yml +9 -11
  6. data/doc/developer_docs.md +1 -0
  7. data/doc/i18n.md +85 -0
  8. data/doc/installation.md +321 -0
  9. data/lib/hammer_cli.rb +3 -0
  10. data/lib/hammer_cli/abstract.rb +15 -24
  11. data/lib/hammer_cli/apipie/command.rb +13 -7
  12. data/lib/hammer_cli/apipie/options.rb +14 -16
  13. data/lib/hammer_cli/apipie/read_command.rb +6 -1
  14. data/lib/hammer_cli/apipie/resource.rb +48 -58
  15. data/lib/hammer_cli/apipie/write_command.rb +5 -1
  16. data/lib/hammer_cli/completer.rb +77 -21
  17. data/lib/hammer_cli/connection.rb +44 -0
  18. data/lib/hammer_cli/exception_handler.rb +15 -4
  19. data/lib/hammer_cli/exceptions.rb +6 -0
  20. data/lib/hammer_cli/i18n.rb +95 -0
  21. data/lib/hammer_cli/logger.rb +3 -3
  22. data/lib/hammer_cli/main.rb +12 -11
  23. data/lib/hammer_cli/modules.rb +19 -6
  24. data/lib/hammer_cli/options/normalizers.rb +42 -7
  25. data/lib/hammer_cli/options/option_definition.rb +2 -2
  26. data/lib/hammer_cli/output.rb +1 -0
  27. data/lib/hammer_cli/output/adapter/abstract.rb +20 -0
  28. data/lib/hammer_cli/output/adapter/base.rb +49 -78
  29. data/lib/hammer_cli/output/adapter/csv.rb +5 -5
  30. data/lib/hammer_cli/output/adapter/table.rb +41 -10
  31. data/lib/hammer_cli/output/dsl.rb +1 -1
  32. data/lib/hammer_cli/output/field_filter.rb +21 -0
  33. data/lib/hammer_cli/output/fields.rb +44 -78
  34. data/lib/hammer_cli/output/formatters.rb +38 -0
  35. data/lib/hammer_cli/settings.rb +28 -6
  36. data/lib/hammer_cli/shell.rb +58 -57
  37. data/lib/hammer_cli/utils.rb +14 -0
  38. data/lib/hammer_cli/validator.rb +5 -5
  39. data/lib/hammer_cli/version.rb +1 -1
  40. data/locale/Makefile +64 -0
  41. data/locale/hammer-cli.pot +203 -0
  42. data/locale/zanata.xml +29 -0
  43. data/test/unit/apipie/command_test.rb +42 -25
  44. data/test/unit/apipie/read_command_test.rb +10 -7
  45. data/test/unit/apipie/write_command_test.rb +9 -8
  46. data/test/unit/completer_test.rb +206 -21
  47. data/test/unit/connection_test.rb +68 -0
  48. data/test/unit/fixtures/apipie/architectures.json +153 -0
  49. data/test/unit/fixtures/apipie/documented.json +79 -0
  50. data/test/unit/fixtures/json_input/invalid.json +12 -0
  51. data/test/unit/fixtures/json_input/valid.json +12 -0
  52. data/test/unit/history_test.rb +71 -0
  53. data/test/unit/main_test.rb +9 -0
  54. data/test/unit/modules_test.rb +22 -6
  55. data/test/unit/options/field_filter_test.rb +27 -0
  56. data/test/unit/options/normalizers_test.rb +53 -0
  57. data/test/unit/output/adapter/base_test.rb +162 -10
  58. data/test/unit/output/adapter/csv_test.rb +16 -3
  59. data/test/unit/output/adapter/table_test.rb +97 -13
  60. data/test/unit/output/dsl_test.rb +74 -6
  61. data/test/unit/output/fields_test.rb +93 -62
  62. data/test/unit/output/formatters_test.rb +47 -0
  63. data/test/unit/settings_test.rb +35 -4
  64. data/test/unit/utils_test.rb +45 -0
  65. metadata +85 -4
  66. data/test/unit/apipie/fake_api.rb +0 -101
@@ -20,15 +20,15 @@ describe HammerCLI::Output::Dsl do
20
20
  dsl.fields.length.must_equal 0
21
21
  end
22
22
 
23
- context "fields" do
24
- it "should create DataField as default field type" do
23
+ describe "fields" do
24
+ it "should create Field as default field type" do
25
25
  dsl.build do
26
26
  field :f, "F"
27
27
  end
28
- first_field.class.must_equal Fields::DataField
28
+ first_field.class.must_equal Fields::Field
29
29
  end
30
30
 
31
- it "should create DataField of desired type" do
31
+ it "should create field of desired type" do
32
32
  dsl.build do
33
33
  field :f, "F", CustomFieldType
34
34
  end
@@ -56,7 +56,7 @@ describe HammerCLI::Output::Dsl do
56
56
  end
57
57
  end
58
58
 
59
- context "custom fields" do
59
+ describe "custom fields" do
60
60
 
61
61
  let(:options) {{:a => 1, :b => 2}}
62
62
 
@@ -76,7 +76,7 @@ describe HammerCLI::Output::Dsl do
76
76
 
77
77
  end
78
78
 
79
- context "path definition" do
79
+ describe "path definition" do
80
80
 
81
81
  it "from appends to path" do
82
82
  dsl.build do
@@ -114,6 +114,74 @@ describe HammerCLI::Output::Dsl do
114
114
  end
115
115
 
116
116
 
117
+ describe "label" do
118
+
119
+ it "creates field of type Label" do
120
+ dsl.build do
121
+ label "Label"
122
+ end
123
+ first_field.class.must_equal Fields::Label
124
+ end
125
+
126
+ it "allows to define subfields with dsl" do
127
+ dsl.build do
128
+ label "Label" do
129
+ field :a, "A"
130
+ field :b, "B"
131
+ end
132
+ end
133
+
134
+ first_field.fields.map(&:label).must_equal ["A", "B"]
135
+ end
136
+
137
+ it "sets correct path to subfields" do
138
+ dsl.build do
139
+ from :nest do
140
+ label "Label" do
141
+ field :a, "A"
142
+ field :b, "B"
143
+ end
144
+ end
145
+ end
146
+
147
+ first_field.fields.map(&:path).must_equal [[:a], [:b]]
148
+ end
149
+
150
+ end
151
+
152
+
153
+ describe "collection" do
154
+
155
+ it "creates field of type Collection" do
156
+ dsl.build do
157
+ collection :f, "F"
158
+ end
159
+ first_field.class.must_equal Fields::Collection
160
+ end
161
+
162
+ it "allows to define subfields with dsl" do
163
+ dsl.build do
164
+ collection :nest, "Label" do
165
+ field :a, "A"
166
+ field :b, "B"
167
+ end
168
+ end
169
+
170
+ first_field.fields.map(&:label).must_equal ["A", "B"]
171
+ end
172
+
173
+ it "sets correct path to subfields" do
174
+ dsl.build do
175
+ collection :nest, "Label" do
176
+ field :a, "A"
177
+ field :b, "B"
178
+ end
179
+ end
180
+
181
+ first_field.fields.map(&:path).must_equal [[:a], [:b]]
182
+ end
183
+
184
+ end
117
185
 
118
186
  end
119
187
 
@@ -1,97 +1,128 @@
1
1
  require File.join(File.dirname(__FILE__), '../test_helper')
2
2
 
3
3
 
4
+
4
5
  describe Fields::Field do
5
6
 
6
- let(:field) { Fields::Field.new }
7
+ let(:label) { "Some Label" }
8
+ let(:path) { [:address, :city, :name] }
9
+ let(:field) { Fields::Field.new :label => label, :path => path, :some => :parameter }
10
+ let(:blank_field) { Fields::Field.new :label => label, :path => path, :hide_blank => true }
7
11
 
8
- describe "get_value" do
9
- it "should exist" do
10
- assert field.respond_to? :get_value
11
- end
12
12
 
13
- it "should take data as a parameter" do
14
- field.method(:get_value).arity.must_equal 1
15
- end
13
+ it "stores label from constructor" do
14
+ field.label.must_equal label
16
15
  end
17
16
 
18
- end
17
+ it "stores path from constructor" do
18
+ field.path.must_equal path
19
+ end
19
20
 
20
- describe Fields::LabeledField do
21
+ it "default path should be empty array" do
22
+ Fields::Field.new.path.must_equal []
23
+ end
21
24
 
22
- let(:label) { "Some Label" }
23
- let(:field) { Fields::LabeledField.new :label => label }
25
+ describe "parameters" do
24
26
 
25
- context "labels" do
26
- it "has label" do
27
- assert field.respond_to? :label
27
+ it "returns all parameters passed to a filed" do
28
+ expected_params = {
29
+ :label => label,
30
+ :path => path,
31
+ :some => :parameter
32
+ }
33
+ field.parameters.must_equal expected_params
28
34
  end
29
35
 
30
- it "is possible to set label in constructor" do
31
- field.label.must_equal label
32
- end
33
36
  end
34
37
 
35
- end
38
+ describe "display?" do
36
39
 
37
- describe Fields::DataField do
40
+ context "blank is allowed" do
38
41
 
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
- }}
42
+ it "returns false the value is nil" do
43
+ field.display?(nil).must_equal true
44
+ end
60
45
 
61
- let(:label) { "Some Label" }
62
- let(:path) { [:address, :city, :name] }
63
- let(:field) { Fields::DataField.new :label => label, :path => path }
46
+ it "returns true when there is some data under the path" do
47
+ field.display?("some value").must_equal true
48
+ end
49
+ end
64
50
 
65
- it "stores label from constructor" do
66
- field.label.must_equal label
67
- end
68
51
 
69
- it "stores path from constructor" do
70
- field.path.must_equal path
71
- end
52
+ context "blank is not allowed" do
53
+
54
+ it "returns false the value is nil" do
55
+ blank_field.display?(nil).must_equal false
56
+ end
57
+
58
+ it "returns true when there is some data under the path" do
59
+ blank_field.display?("some value").must_equal true
60
+ end
61
+ end
72
62
 
73
- it "default path should be empty array" do
74
- Fields::DataField.new.path.must_equal []
75
63
  end
76
64
 
77
- context "getting data" do
65
+ describe "hide_blank?" do
78
66
 
79
- it "should pick correct value" do
80
- field.get_value(symbol_data).must_equal symbol_data[:address][:city][:name]
67
+ it "defaults to false" do
68
+ Fields::Field.new.hide_blank?.must_equal false
81
69
  end
82
70
 
83
- it "should pick correct value independent of key type" do
84
- field.get_value(string_data).must_equal string_data["address"]["city"]["name"]
71
+ it "can be set to true in the constructor" do
72
+ blank_field.hide_blank?.must_equal true
85
73
  end
86
74
 
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"]
75
+ end
76
+
77
+ end
78
+
79
+
80
+ describe Fields::ContainerField do
81
+
82
+ describe "display?" do
83
+
84
+ context "blank is allowed" do
85
+ let(:field) { Fields::ContainerField.new :label => "Label" }
86
+
87
+ it "returns false the value is nil" do
88
+ field.display?(nil).must_equal true
89
+ end
90
+
91
+ it "returns false the value is empty array" do
92
+ field.display?([]).must_equal true
93
+ end
94
+
95
+ it "returns false the value is empty hash" do
96
+ field.display?({}).must_equal true
97
+ end
98
+
99
+ it "returns true when there is some data under the path" do
100
+ field.display?(["some value"]).must_equal true
101
+ end
102
+
90
103
  end
91
104
 
105
+ context "blank is not allowed" do
106
+ let(:field) { Fields::ContainerField.new :label => "Label", :hide_blank => true }
92
107
 
93
- end
108
+ it "returns false the value is nil" do
109
+ field.display?(nil).must_equal false
110
+ end
94
111
 
95
- end
112
+ it "returns false the value is empty array" do
113
+ field.display?([]).must_equal false
114
+ end
96
115
 
116
+ it "returns false the value is empty hash" do
117
+ field.display?({}).must_equal false
118
+ end
97
119
 
120
+ it "returns true when there is some data under the path" do
121
+ field.display?(["some value"]).must_equal true
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
@@ -91,3 +91,50 @@ describe HammerCLI::Output::Formatters::ListFormatter do
91
91
  formatter.format('some string').must_equal 'some string'
92
92
  end
93
93
  end
94
+
95
+
96
+ describe HammerCLI::Output::Formatters::KeyValueFormatter do
97
+
98
+ let(:params) {
99
+ {
100
+ :name => "Name",
101
+ "value" => "Value",
102
+ }
103
+ }
104
+
105
+ it "serializes the value" do
106
+ formatter = HammerCLI::Output::Formatters::KeyValueFormatter.new
107
+ formatter.format(params).must_equal 'Name => Value'
108
+ end
109
+
110
+ it "returns empty string when the input is nil" do
111
+ formatter = HammerCLI::Output::Formatters::KeyValueFormatter.new
112
+ formatter.format(nil).must_equal ''
113
+ end
114
+
115
+ it "returns empty string value when the input is not a hash" do
116
+ formatter = HammerCLI::Output::Formatters::KeyValueFormatter.new
117
+ formatter.format('some string').must_equal ''
118
+ end
119
+ end
120
+
121
+
122
+
123
+ describe HammerCLI::Output::Formatters::LongTextFormatter do
124
+
125
+ it "prepends new line" do
126
+ formatter = HammerCLI::Output::Formatters::LongTextFormatter.new
127
+ formatter.format("Some\nmultiline\ntext").must_equal "\n Some\n multiline\n text"
128
+ end
129
+
130
+ it "accepts nil" do
131
+ formatter = HammerCLI::Output::Formatters::LongTextFormatter.new
132
+ formatter.format(nil).must_equal "\n "
133
+ end
134
+
135
+ it "enables to switch indentation off" do
136
+ formatter = HammerCLI::Output::Formatters::LongTextFormatter.new(:indent => false)
137
+ formatter.format("Some\nmultiline\ntext").must_equal "\nSome\nmultiline\ntext"
138
+ end
139
+
140
+ end
@@ -43,6 +43,12 @@ describe HammerCLI::Settings do
43
43
  settings.get(:b).must_equal 2
44
44
  end
45
45
 
46
+ it "dumps all settings" do
47
+ data = {:a => 1, :b => 2}
48
+ settings.load(data)
49
+ settings.dump.must_equal data
50
+ end
51
+
46
52
  it "merges settings on second load" do
47
53
  settings.load({:a => 1, :b => 2, :d => {:e => 4, :f => 5}})
48
54
  settings.load({:b => 'B', :c => 'C', :d => {:e => 'E'}})
@@ -60,7 +66,7 @@ describe HammerCLI::Settings do
60
66
  settings.get(:b).must_be_nil
61
67
  end
62
68
 
63
- context "load from file" do
69
+ context "load from paths" do
64
70
 
65
71
  let(:config1) do
66
72
  config1 = Tempfile.new 'config'
@@ -85,22 +91,47 @@ describe HammerCLI::Settings do
85
91
  end
86
92
 
87
93
  it "loads settings from file" do
88
- settings.load_from_file [config2.path, config1.path]
94
+ settings.load_from_paths [config2.path, config1.path]
89
95
  settings.get(:host).must_equal 'https://localhost.localdomain/'
90
96
  settings.get(:username).must_equal 'admin'
91
97
  end
92
98
 
93
99
  it "clears path history on clear invokation" do
94
- settings.load_from_file [config2.path]
100
+ settings.load_from_paths [config2.path]
95
101
  settings.clear
96
102
  settings.path_history.must_equal []
97
103
  end
98
104
 
99
105
  it "store config path history" do
100
- settings.load_from_file [config2.path, config1.path]
106
+ settings.load_from_paths [config2.path, config1.path]
101
107
  settings.path_history.must_equal [config1.path, config2.path]
102
108
  end
103
109
 
110
+ it "loads settings from dir" do
111
+ dir = Dir.mktmpdir
112
+ begin
113
+ File.open(File.join(dir, "cli_config.yml"), "w") do |f|
114
+ f.write(":param1: 'value1'\n")
115
+ end
116
+ module_dir = File.join(dir, 'cli.modules.d')
117
+ Dir.mkdir(module_dir)
118
+ File.open(File.join(module_dir, "cli_config.yml"), "w") do |f|
119
+ f.write(":module:\n")
120
+ f.write(" :param2: 'value2'\n")
121
+ end
122
+
123
+ settings.load_from_paths [config1.path, dir]
124
+
125
+ settings.get(:host).must_equal 'https://localhost/'
126
+ settings.get(:username).must_equal 'admin'
127
+ settings.get(:param1).must_equal 'value1'
128
+ settings.get(:module, :param2).must_equal 'value2'
129
+
130
+ ensure
131
+ FileUtils.remove_entry dir
132
+ end
133
+
134
+ end
104
135
  end
105
136
  end
106
137
 
@@ -44,5 +44,50 @@ describe String do
44
44
 
45
45
  end
46
46
 
47
+ describe "indent" do
48
+
49
+ it "indents single line string" do
50
+ "line one".indent_with(" ").must_equal " line one"
51
+ end
52
+
53
+ it "indents multi line string" do
54
+ "line one\nline two".indent_with(" ").must_equal " line one\n line two"
55
+ end
56
+
57
+ end
58
+
59
+ describe "interactive?" do
60
+
61
+ before :each do
62
+ @tty = STDOUT.tty?
63
+ STDOUT.stubs(:'tty?').returns(true)
64
+ end
65
+
66
+ after :each do
67
+ STDOUT.stubs(:'tty?').returns(@tty)
68
+ end
69
+
70
+ it "should be true when called in tty" do
71
+ HammerCLI::Settings.load({
72
+ :ui => { :interactive => nil },
73
+ :_params => { :interactive => nil } })
74
+ HammerCLI::interactive?.must_equal true
75
+ end
76
+
77
+ it "should by false when cli arg set" do
78
+ HammerCLI::Settings.load({
79
+ :ui => { :interactive => nil },
80
+ :_params => { :interactive => false } })
81
+ HammerCLI::interactive?.must_equal false
82
+ end
83
+
84
+ it "should by false when turned off in cfg" do
85
+ HammerCLI::Settings.load({
86
+ :ui => { :interactive => false },
87
+ :_params => { :interactive => nil } })
88
+ HammerCLI::interactive?.must_equal false
89
+ end
90
+ end
91
+
47
92
  end
48
93