hammer_cli 0.0.18 → 0.1.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.
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