command_kit 0.1.0.pre1

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 (98) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +29 -0
  4. data/.gitignore +7 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +29 -0
  8. data/Gemfile +14 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +283 -0
  11. data/Rakefile +23 -0
  12. data/command_kit.gemspec +60 -0
  13. data/gemspec.yml +14 -0
  14. data/lib/command_kit.rb +1 -0
  15. data/lib/command_kit/arguments.rb +161 -0
  16. data/lib/command_kit/arguments/argument.rb +111 -0
  17. data/lib/command_kit/arguments/argument_value.rb +81 -0
  18. data/lib/command_kit/arguments/usage.rb +6 -0
  19. data/lib/command_kit/colors.rb +355 -0
  20. data/lib/command_kit/command.rb +42 -0
  21. data/lib/command_kit/command_name.rb +95 -0
  22. data/lib/command_kit/commands.rb +299 -0
  23. data/lib/command_kit/commands/auto_load.rb +153 -0
  24. data/lib/command_kit/commands/auto_load/subcommand.rb +90 -0
  25. data/lib/command_kit/commands/auto_require.rb +138 -0
  26. data/lib/command_kit/commands/command.rb +12 -0
  27. data/lib/command_kit/commands/help.rb +43 -0
  28. data/lib/command_kit/commands/parent_command.rb +21 -0
  29. data/lib/command_kit/commands/subcommand.rb +51 -0
  30. data/lib/command_kit/console.rb +141 -0
  31. data/lib/command_kit/description.rb +89 -0
  32. data/lib/command_kit/env.rb +43 -0
  33. data/lib/command_kit/env/home.rb +71 -0
  34. data/lib/command_kit/env/path.rb +71 -0
  35. data/lib/command_kit/examples.rb +99 -0
  36. data/lib/command_kit/exception_handler.rb +55 -0
  37. data/lib/command_kit/help.rb +62 -0
  38. data/lib/command_kit/help/man.rb +125 -0
  39. data/lib/command_kit/inflector.rb +84 -0
  40. data/lib/command_kit/main.rb +103 -0
  41. data/lib/command_kit/options.rb +179 -0
  42. data/lib/command_kit/options/option.rb +171 -0
  43. data/lib/command_kit/options/option_value.rb +90 -0
  44. data/lib/command_kit/options/parser.rb +227 -0
  45. data/lib/command_kit/options/quiet.rb +53 -0
  46. data/lib/command_kit/options/usage.rb +6 -0
  47. data/lib/command_kit/options/verbose.rb +55 -0
  48. data/lib/command_kit/options/version.rb +62 -0
  49. data/lib/command_kit/os.rb +47 -0
  50. data/lib/command_kit/pager.rb +115 -0
  51. data/lib/command_kit/printing.rb +32 -0
  52. data/lib/command_kit/printing/indent.rb +78 -0
  53. data/lib/command_kit/program_name.rb +57 -0
  54. data/lib/command_kit/stdio.rb +138 -0
  55. data/lib/command_kit/usage.rb +102 -0
  56. data/lib/command_kit/version.rb +4 -0
  57. data/lib/command_kit/xdg.rb +138 -0
  58. data/spec/arguments/argument_spec.rb +169 -0
  59. data/spec/arguments/argument_value_spec.rb +126 -0
  60. data/spec/arguments_spec.rb +213 -0
  61. data/spec/colors_spec.rb +470 -0
  62. data/spec/command_kit_spec.rb +8 -0
  63. data/spec/command_name_spec.rb +130 -0
  64. data/spec/command_spec.rb +49 -0
  65. data/spec/commands/auto_load/subcommand_spec.rb +82 -0
  66. data/spec/commands/auto_load_spec.rb +128 -0
  67. data/spec/commands/auto_require_spec.rb +142 -0
  68. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +10 -0
  69. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +10 -0
  70. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +10 -0
  71. data/spec/commands/help_spec.rb +66 -0
  72. data/spec/commands/parent_command_spec.rb +40 -0
  73. data/spec/commands/subcommand_spec.rb +99 -0
  74. data/spec/commands_spec.rb +767 -0
  75. data/spec/console_spec.rb +201 -0
  76. data/spec/description_spec.rb +203 -0
  77. data/spec/env/home_spec.rb +46 -0
  78. data/spec/env/path_spec.rb +78 -0
  79. data/spec/env_spec.rb +123 -0
  80. data/spec/examples_spec.rb +235 -0
  81. data/spec/exception_handler_spec.rb +103 -0
  82. data/spec/help_spec.rb +119 -0
  83. data/spec/inflector_spec.rb +104 -0
  84. data/spec/main_spec.rb +179 -0
  85. data/spec/options/option_spec.rb +258 -0
  86. data/spec/options/option_value_spec.rb +67 -0
  87. data/spec/options/parser_spec.rb +265 -0
  88. data/spec/options_spec.rb +137 -0
  89. data/spec/os_spec.rb +46 -0
  90. data/spec/pager_spec.rb +154 -0
  91. data/spec/printing/indent_spec.rb +130 -0
  92. data/spec/printing_spec.rb +76 -0
  93. data/spec/program_name_spec.rb +62 -0
  94. data/spec/spec_helper.rb +6 -0
  95. data/spec/stdio_spec.rb +264 -0
  96. data/spec/usage_spec.rb +237 -0
  97. data/spec/xdg_spec.rb +191 -0
  98. metadata +156 -0
data/spec/help_spec.rb ADDED
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/help'
3
+
4
+ describe CommandKit::Help do
5
+ module TestHelp
6
+ class DefaultCmd
7
+ include CommandKit::Help
8
+ end
9
+
10
+ class TestCommandWithInitialize
11
+ include CommandKit::Help
12
+
13
+ attr_reader :foo
14
+
15
+ attr_reader :bar
16
+
17
+ def initialize(foo: 'foo', bar: 'bar', **kwargs)
18
+ super(**kwargs)
19
+
20
+ @foo = foo
21
+ @bar = bar
22
+ end
23
+ end
24
+ end
25
+
26
+ let(:command_class) { TestHelp::TestCmd }
27
+
28
+ describe ".help" do
29
+ subject { command_class }
30
+
31
+ context "when no #initialize method is defined" do
32
+ let(:command_class) { TestHelp::DefaultCmd }
33
+ let(:instance) { command_class.new }
34
+
35
+ it "must initialize the command object and call #help" do
36
+ expect(subject).to receive(:new).with(no_args).and_return(instance)
37
+ expect(instance).to receive(:help).with(no_args)
38
+
39
+ subject.help()
40
+ end
41
+ end
42
+
43
+ context "when an #initialize method is defined" do
44
+ let(:command_class) { TestHelp::TestCommandWithInitialize }
45
+ let(:instance) { command_class.new }
46
+
47
+ context "and given no arguments" do
48
+ it "must initialize the command object and call #help" do
49
+ expect(subject).to receive(:new).with(no_args).and_return(instance)
50
+ expect(instance).to receive(:help).with(no_args)
51
+
52
+ subject.help()
53
+ end
54
+ end
55
+
56
+ context "and given keyword arguments" do
57
+ let(:kwargs) { {foo: 'custom foo', bar: 'custom bar'} }
58
+ let(:instance) { command_class.new(**kwargs) }
59
+
60
+ it "must pass the keyword arguments .new then call #help" do
61
+ expect(subject).to receive(:new).with(**kwargs).and_return(instance)
62
+ expect(instance).to receive(:help).with(no_args)
63
+
64
+ subject.help(**kwargs)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ subject { command_class.new }
71
+
72
+ describe "#help" do
73
+ context "when there is no superclass #help method" do
74
+ module TestHelp
75
+ class SuperclassWithoutHelp
76
+ end
77
+
78
+ class SubclassOfSuperclassWithoutHelp < SuperclassWithoutHelp
79
+ include CommandKit::Help
80
+ end
81
+ end
82
+
83
+ let(:command_superclass) { TestHelp::SuperclassWithoutHelp }
84
+ let(:command_class) { TestHelp::SubclassOfSuperclassWithoutHelp }
85
+
86
+ it "must not attempt to call the superclass'es #help" do
87
+ allow_any_instance_of(command_class).to receive(:help)
88
+ expect_any_instance_of(command_superclass).to_not receive(:help)
89
+
90
+ subject.help()
91
+ end
92
+ end
93
+
94
+ context "when the superclass defines it's own #help method" do
95
+ module TestHelp
96
+ class SuperclassWithHelp
97
+
98
+ def help
99
+ puts 'superclass'
100
+ end
101
+
102
+ end
103
+
104
+ class SubclassOfSuperclassWithHelp < SuperclassWithHelp
105
+ include CommandKit::Help
106
+ end
107
+ end
108
+
109
+ let(:command_superclass) { TestHelp::SuperclassWithHelp }
110
+ let(:command_class) { TestHelp::SubclassOfSuperclassWithHelp }
111
+
112
+ it "must call the superclass'es #help" do
113
+ expect_any_instance_of(command_superclass).to receive(:help)
114
+
115
+ subject.help()
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/inflector'
3
+
4
+ describe Inflector do
5
+ describe ".demodularize" do
6
+ context "when given a single class or module name" do
7
+ let(:name) { 'Foo' }
8
+
9
+ it "must return the class or module name unchanged" do
10
+ expect(subject.demodularize(name)).to eq(name)
11
+ end
12
+ end
13
+
14
+ context "when given a class or module name with a leading namespace" do
15
+ let(:namespace) { 'Foo::Bar' }
16
+ let(:constant) { "Baz" }
17
+ let(:name) { "#{namespace}::#{constant}" }
18
+
19
+ it "must return the constant name, without the leading namespace" do
20
+ expect(subject.demodularize(name)).to eq(constant)
21
+ end
22
+ end
23
+
24
+ context "when given a non-String" do
25
+ it "must convert it to a String" do
26
+ expect(subject.demodularize(:"Foo::Bar")).to eq('Bar')
27
+ end
28
+ end
29
+ end
30
+
31
+ describe ".underscore" do
32
+ it "must convert CamelCase to camel_case" do
33
+ expect(subject.underscore('CamelCase')).to eq('camel_case')
34
+ end
35
+
36
+ it "must convert camelCase to camel_case" do
37
+ expect(subject.underscore('camelCase')).to eq('camel_case')
38
+ end
39
+
40
+ it "must convert Camel to camel" do
41
+ expect(subject.underscore('Camel')).to eq('camel')
42
+ end
43
+
44
+ it "must convert CAMEL to camel" do
45
+ expect(subject.underscore('CAMEL')).to eq('camel')
46
+ end
47
+
48
+ context "when given a String containing '/' characters" do
49
+ it "must replace dashes with underscores" do
50
+ expect(subject.underscore('foo-bar')).to eq('foo_bar')
51
+ end
52
+ end
53
+
54
+ context "when given a non-String" do
55
+ it "must convert it to a String" do
56
+ expect(subject.underscore(:CamelCase)).to eq('camel_case')
57
+ end
58
+ end
59
+ end
60
+
61
+ describe ".dasherize" do
62
+ it "must replace all underscores with dashes" do
63
+ expect(subject.dasherize("foo_bar")).to eq('foo-bar')
64
+ end
65
+
66
+ context "when given a non-String" do
67
+ it "must convert it to a String" do
68
+ expect(subject.dasherize(:foo_bar)).to eq('foo-bar')
69
+ end
70
+ end
71
+ end
72
+
73
+ describe ".camelize" do
74
+ context "when given a string with no underscores" do
75
+ it "must capitalize the string" do
76
+ expect(subject.camelize('foo')).to eq('Foo')
77
+ end
78
+ end
79
+
80
+ context "when given a string with underscores" do
81
+ it "must capitalize each word and remove all underscores" do
82
+ expect(subject.camelize('foo_bar')).to eq('FooBar')
83
+ end
84
+ end
85
+
86
+ context "when given a string with dashes" do
87
+ it "must capitalize each word and remove all dashes" do
88
+ expect(subject.camelize('foo-bar')).to eq('FooBar')
89
+ end
90
+ end
91
+
92
+ context "when given a string containing '/' characters" do
93
+ it "must replace the '/' characters with '::' strings" do
94
+ expect(subject.camelize('foo_bar/baz_quox')).to eq('FooBar::BazQuox')
95
+ end
96
+ end
97
+
98
+ context "when given a non-String" do
99
+ it "must convert it to a String" do
100
+ expect(subject.camelize(:foo_bar)).to eq('FooBar')
101
+ end
102
+ end
103
+ end
104
+ end
data/spec/main_spec.rb ADDED
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/main'
3
+
4
+ describe Main do
5
+ module TestMain
6
+ class TestCommand
7
+ include CommandKit::Main
8
+ end
9
+
10
+ class TestCommandWithInitialize
11
+ include CommandKit::Main
12
+
13
+ attr_reader :foo
14
+
15
+ attr_reader :bar
16
+
17
+ def initialize(foo: 'foo', bar: 'bar', **kwargs)
18
+ super(**kwargs)
19
+
20
+ @foo = foo
21
+ @bar = bar
22
+ end
23
+ end
24
+ end
25
+
26
+ let(:command_class) { TestMain::TestCommand }
27
+
28
+ describe ".start" do
29
+ subject { command_class }
30
+
31
+ it "must exit with 0 by default" do
32
+ expect(subject).to receive(:exit).with(0)
33
+
34
+ subject.start
35
+ end
36
+
37
+ context "when given an argv argument" do
38
+ let(:argv) { %w[one two three] }
39
+
40
+ it "must pass argv to .main" do
41
+ expect(subject).to receive(:main).with(argv)
42
+ allow(subject).to receive(:exit)
43
+
44
+ subject.start(argv)
45
+ end
46
+ end
47
+
48
+ context "when given keyword arguments" do
49
+ let(:command_class) { TestMain::TestCommandWithInitialize }
50
+
51
+ let(:kwargs) { {foo: 'custom foo', bar: 'custom bar'} }
52
+
53
+ it "must pass the keyword arguments down to .main" do
54
+ expect(subject).to receive(:main).with(ARGV, **kwargs)
55
+ allow(subject).to receive(:exit)
56
+
57
+ subject.start(**kwargs)
58
+ end
59
+ end
60
+
61
+ context "when Interrupt is raised" do
62
+ module TestMain
63
+ class TestCommandWithInterrupt
64
+ include CommandKit::Main
65
+
66
+ def main(*argv)
67
+ raise(Interrupt)
68
+ end
69
+ end
70
+ end
71
+
72
+ let(:command_class) { TestMain::TestCommandWithInterrupt }
73
+
74
+ it "must exit with 130" do
75
+ expect(command_class).to receive(:exit).with(130)
76
+
77
+ command_class.start
78
+ end
79
+ end
80
+
81
+ context "when Errno::EPIPE is raised" do
82
+ module TestMain
83
+ class TestCommandWithBrokenPipe
84
+ include CommandKit::Main
85
+
86
+ def main(*argv)
87
+ raise(Errno::EPIPE)
88
+ end
89
+ end
90
+ end
91
+
92
+ let(:command_class) { TestMain::TestCommandWithBrokenPipe }
93
+
94
+ it "must exit with 0" do
95
+ expect(command_class).to receive(:exit).with(0)
96
+
97
+ command_class.start
98
+ end
99
+ end
100
+ end
101
+
102
+ module TestMain
103
+ class TestCommandWithSystemExit
104
+
105
+ include CommandKit::Main
106
+
107
+ def run(*argv)
108
+ raise(SystemExit.new(-1))
109
+ end
110
+
111
+ end
112
+ end
113
+
114
+ describe ".main" do
115
+ subject { command_class }
116
+
117
+ it "must return 0 by default" do
118
+ expect(subject.main).to eq(0)
119
+ end
120
+
121
+ let(:command_class) { TestMain::TestCommandWithInitialize }
122
+
123
+ context "when given a custom argv" do
124
+ let(:instance) { command_class.new }
125
+ let(:argv) { %w[one two three] }
126
+
127
+ it "must call #main with the custom argv" do
128
+ expect(subject).to receive(:new).with(no_args).and_return(instance)
129
+ expect(instance).to receive(:main).with(argv)
130
+
131
+ subject.main(argv)
132
+ end
133
+ end
134
+
135
+ context "when given keyword arguments" do
136
+ let(:kwargs) { {foo: 'custom foo', bar: 'custom bar'} }
137
+ let(:instance) { command_class.new(**kwargs) }
138
+
139
+ it "must pass the keyword arguments .new then call #main" do
140
+ expect(subject).to receive(:new).with(**kwargs).and_return(instance)
141
+ expect(instance).to receive(:main).with([])
142
+
143
+ subject.main(**kwargs)
144
+ end
145
+ end
146
+
147
+ context "when #main raises SystemExit" do
148
+ let(:command_class) { TestMain::TestCommandWithSystemExit }
149
+
150
+ it "must rescue SystemExit and return the exit status code" do
151
+ expect(subject.main()).to eq(-1)
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "#main" do
157
+ subject { command_class.new }
158
+
159
+ it "must provide a default #main" do
160
+ expect(subject).to respond_to(:main)
161
+ end
162
+
163
+ it "must return 0 by default" do
164
+ expect(subject.main).to eq(0)
165
+ end
166
+
167
+ it "must accept arbitrary argv" do
168
+ expect { subject.main([1,2,3]) }.to_not raise_error
169
+ end
170
+
171
+ context "when #run raises SystemExit" do
172
+ let(:command_class) { TestMain::TestCommandWithSystemExit }
173
+
174
+ it "must rescue SystemExit and return the exit status code" do
175
+ expect(subject.main()).to eq(-1)
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,258 @@
1
+ require 'spec_helper'
2
+ require 'command_kit/options/option'
3
+
4
+ describe Options::Option do
5
+ let(:name) { :foo }
6
+ let(:short) { nil }
7
+ let(:long) { '--foo' }
8
+ let(:equals) { false }
9
+ let(:value) do
10
+ {
11
+ usage: 'FOO',
12
+ required: true
13
+ }
14
+ end
15
+ let(:desc) { 'Foo option' }
16
+ let(:block) do
17
+ ->(arg) { @foo = arg }
18
+ end
19
+
20
+ subject do
21
+ described_class.new name, short: short,
22
+ long: long,
23
+ equals: equals,
24
+ desc: desc,
25
+ value: value,
26
+ &block
27
+ end
28
+
29
+ describe "#initialize" do
30
+ context "when the short: keyword is given" do
31
+ subject { described_class.new(name, short: short, desc: desc) }
32
+
33
+ it "must set #short" do
34
+ expect(subject.short).to eq(short)
35
+ end
36
+ end
37
+
38
+ context "when the short: keyword is not given" do
39
+ subject { described_class.new(name, desc: desc) }
40
+
41
+ it { expect(subject.short).to be(nil) }
42
+ end
43
+
44
+ context "when the long: keyword is given" do
45
+ let(:long) { '--opt' }
46
+
47
+ subject { described_class.new(name, long: long, desc: desc) }
48
+
49
+ it "must set #long" do
50
+ expect(subject.long).to eq(long)
51
+ end
52
+ end
53
+
54
+ context "when the long: keyword is not given" do
55
+ subject { described_class.new(name, desc: desc) }
56
+
57
+ it "default #long to a '--option' flag based on #name" do
58
+ expect(subject.long).to eq("--#{name}")
59
+ end
60
+ end
61
+
62
+ context "when the equals: keyword is given" do
63
+ let(:equals) { true }
64
+
65
+ subject { described_class.new(name, equals: equals, desc: desc) }
66
+
67
+ it "must set #equals" do
68
+ expect(subject.equals).to eq(equals)
69
+ end
70
+ end
71
+
72
+ context "when the equals: keyword is not given" do
73
+ subject { described_class.new(name, desc: desc) }
74
+
75
+ it { expect(subject.equals).to be(false) }
76
+ end
77
+
78
+ context "when the values: keyword is given" do
79
+ let(:value) { {} }
80
+ subject { described_class.new(name, value: {}, desc: desc) }
81
+
82
+ it "must initialize #value" do
83
+ expect(subject.value).to be_kind_of(Options::OptionValue)
84
+ end
85
+ end
86
+
87
+ context "when the values: keyword is not given" do
88
+ subject { described_class.new(name, desc: desc) }
89
+
90
+ it { expect(subject.value).to be(nil) }
91
+ end
92
+
93
+ context "when the desc: keyword is given" do
94
+ subject { described_class.new(name, desc: desc) }
95
+
96
+ it "must set #desc" do
97
+ expect(subject.desc).to eq(desc)
98
+ end
99
+ end
100
+
101
+ context "when the desc: keyword is not given" do
102
+ it do
103
+ expect {
104
+ described_class.new(name)
105
+ }.to raise_error(ArgumentError)
106
+ end
107
+ end
108
+
109
+ context "when a block is given" do
110
+ subject { described_class.new(name, desc: desc, &block) }
111
+
112
+ it "must set #block" do
113
+ expect(subject.block).to eq(block)
114
+ end
115
+ end
116
+
117
+ context "when no block is given" do
118
+ subject { described_class.new(name, desc: desc) }
119
+
120
+ it { expect(subject.block).to be(nil) }
121
+ end
122
+ end
123
+
124
+ describe "#equals?" do
125
+ context "when initialized with equals: true" do
126
+ let(:equals) { true }
127
+
128
+ it { expect(subject.equals?).to be(true) }
129
+ end
130
+
131
+ context "when initialized with equals: false" do
132
+ let(:equals) { false }
133
+
134
+ it { expect(subject.equals?).to be(false) }
135
+ end
136
+ end
137
+
138
+ describe "#separator" do
139
+ context "when #value is initialized" do
140
+ context "and #equals? is true" do
141
+ let(:equals) { true }
142
+
143
+ it { expect(subject.separator).to eq('=') }
144
+ end
145
+
146
+ context "and #equals? is false" do
147
+ let(:equals) { false }
148
+
149
+ it { expect(subject.separator).to eq(' ') }
150
+ end
151
+ end
152
+
153
+ context "when #value is not initialized" do
154
+ let(:value) { nil }
155
+
156
+ it { expect(subject.separator).to be(nil) }
157
+ end
158
+ end
159
+
160
+ describe "#usage" do
161
+ let(:long) { '--foo' }
162
+
163
+ it "must start with the long '--option'" do
164
+ expect(subject.usage.last).to start_with(long)
165
+ end
166
+
167
+ context "when #value is initialized" do
168
+ it "must return '--option USAGE'" do
169
+ expect(subject.usage.last).to eq("#{long} #{subject.value.usage}")
170
+ end
171
+
172
+ context "and #equals? is true" do
173
+ let(:equals) { true }
174
+
175
+ it "must return '--option=USAGE'" do
176
+ expect(subject.usage.last).to eq("#{long}=#{subject.value.usage}")
177
+ end
178
+ end
179
+ end
180
+
181
+ context "when #short is not nil" do
182
+ let(:short) { '-f' }
183
+
184
+ it "to have two elements" do
185
+ expect(subject.usage.length).to eq(2)
186
+ end
187
+
188
+ it "the first element should be the short option" do
189
+ expect(subject.usage[0]).to eq(short)
190
+ end
191
+ end
192
+ end
193
+
194
+ describe "#value?" do
195
+ context "when #value has been initialized" do
196
+ let(:value) { {} }
197
+
198
+ it { expect(subject.value?).to be(true) }
199
+ end
200
+
201
+ context "when #value has not been initialized" do
202
+ let(:value) { nil }
203
+
204
+ it { expect(subject.value?).to be(false) }
205
+ end
206
+ end
207
+
208
+ describe "#type" do
209
+ context "when #value has been initialized and has a #type" do
210
+ let(:type) { String }
211
+ let(:value) { {type: type} }
212
+
213
+ it "must return the #value.type" do
214
+ expect(subject.type).to eq(type)
215
+ end
216
+ end
217
+
218
+ context "when #value has not been initialized" do
219
+ let(:value) { nil }
220
+
221
+ it { expect(subject.type).to be(nil) }
222
+ end
223
+ end
224
+
225
+ describe "#default_value" do
226
+ context "when #value has been initialized and has a #default" do
227
+ let(:default) { "" }
228
+ let(:value) { {default: default} }
229
+
230
+ it "must return the #value.default_value" do
231
+ expect(subject.default_value).to eq(default)
232
+ end
233
+ end
234
+
235
+ context "when #value has not been initialized" do
236
+ let(:value) { nil }
237
+
238
+ it { expect(subject.default_value).to be(nil) }
239
+ end
240
+ end
241
+
242
+ describe "#desc" do
243
+ let(:desc) { 'Foo option' }
244
+
245
+ it "must return the desc: value" do
246
+ expect(subject.desc).to eq(desc)
247
+ end
248
+
249
+ context "when #value has been initialized with a default value" do
250
+ let(:default) { "foo" }
251
+ let(:value) { {default: default} }
252
+
253
+ it "should reutrn the desc value and '(Default: ...)'" do
254
+ expect(subject.desc).to eq("#{desc} (Default: #{default})")
255
+ end
256
+ end
257
+ end
258
+ end