File: base_spec.rb

package info (click to toggle)
ruby-thor 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 800 kB
  • sloc: ruby: 8,134; makefile: 4; sh: 1
file content (306 lines) | stat: -rw-r--r-- 9,689 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
require "helper"
require "thor/base"

class Amazing
  desc "hello", "say hello"
  def hello
    puts "Hello"
  end
end

describe Thor::Base do
  describe "#initialize" do
    it "sets arguments array" do
      base = MyCounter.new [1, 2]
      expect(base.first).to eq(1)
      expect(base.second).to eq(2)
    end

    it "sets arguments default values" do
      base = MyCounter.new [1]
      expect(base.second).to eq(2)
    end

    it "sets options default values" do
      base = MyCounter.new [1, 2]
      expect(base.options[:third]).to eq(3)
    end

    it "allows options to be given as symbols or strings" do
      base = MyCounter.new [1, 2], :third => 4
      expect(base.options[:third]).to eq(4)

      base = MyCounter.new [1, 2], "third" => 4
      expect(base.options[:third]).to eq(4)
    end

    it "creates options with indifferent access" do
      base = MyCounter.new [1, 2], :third => 3
      expect(base.options["third"]).to eq(3)
    end

    it "creates options with magic predicates" do
      base = MyCounter.new [1, 2], :third => 3
      expect(base.options.third).to eq(3)
    end
  end

  describe "#no_commands" do
    it "avoids methods being added as commands" do
      expect(MyScript.commands.keys).to include("animal")
      expect(MyScript.commands.keys).not_to include("this_is_not_a_command")
      expect(MyScript.commands.keys).not_to include("neither_is_this")
    end
  end

  describe "#argument" do
    it "sets a value as required and creates an accessor for it" do
      expect(MyCounter.start(%w(1 2 --third 3))[0]).to eq(1)
      expect(Scripts::MyScript.start(%w(zoo my_special_param --param=normal_param))).to eq("my_special_param")
    end

    it "does not set a value in the options hash" do
      expect(BrokenCounter.start(%w(1 2 --third 3))[0]).to be nil
    end
  end

  describe "#arguments" do
    it "returns the arguments for the class" do
      expect(MyCounter.arguments.size).to be(2)
    end
  end

  describe ":aliases" do
    it "supports string aliases without a dash prefix" do
      expect(MyCounter.start(%w(1 2 -z 3))[4]).to eq(3)
    end

    it "supports symbol aliases" do
      expect(MyCounter.start(%w(1 2 -y 3))[5]).to eq(3)
      expect(MyCounter.start(%w(1 2 -r 3))[5]).to eq(3)
    end
  end

  describe "#class_option" do
    it "sets options class wise" do
      expect(MyCounter.start(%w(1 2 --third 3))[2]).to eq(3)
    end

    it "does not create an accessor for it" do
      expect(BrokenCounter.start(%w(1 2 --third 3))[3]).to be false
    end
  end

  describe "#class_options" do
    it "sets default options overwriting superclass definitions" do
      options = Scripts::MyScript.class_options
      expect(options[:force]).not_to be_required
    end
  end

  describe "#remove_argument" do
    it "removes previously defined arguments from class" do
      expect(ClearCounter.arguments).to be_empty
    end

    it "undefine accessors if required" do
      expect(ClearCounter.new).not_to respond_to(:first)
      expect(ClearCounter.new).not_to respond_to(:second)
    end
  end

  describe "#remove_class_option" do
    it "removes previous defined class option" do
      expect(ClearCounter.class_options[:third]).to be nil
    end
  end

  describe "#class_options_help" do
    before do
      @content = capture(:stdout) { MyCounter.help(Thor::Base.shell.new) }
    end

    it "shows option's description" do
      expect(@content).to match(/# The third argument/)
    end

    it "shows usage with banner content" do
      expect(@content).to match(/\[\-\-third=THREE\]/)
    end

    it "shows default values below descriptions" do
      expect(@content).to match(/# Default: 3/)
    end

    it "shows options in different groups" do
      expect(@content).to match(/Options\:/)
      expect(@content).to match(/Runtime options\:/)
      expect(@content).to match(/\-p, \[\-\-pretend\]/)
    end

    it "use padding in options that do not have aliases" do
      expect(@content).to match(/^  -t, \[--third/)
      expect(@content).to match(/^          \[--fourth/)
    end

    it "allows extra options to be given" do
      hash = {"Foo" => B.class_options.values}

      content = capture(:stdout) { MyCounter.send(:class_options_help, Thor::Base.shell.new, hash) }
      expect(content).to match(/Foo options\:/)
      expect(content).to match(/--last-name=LAST_NAME/)
    end

    it "displays choices for enums" do
      content = capture(:stdout) { Enum.help(Thor::Base.shell.new) }
      expect(content).to match(/Possible values\: apple, banana/)
    end
  end

  describe "#namespace" do
    it "returns the default class namespace" do
      expect(Scripts::MyScript.namespace).to eq("scripts:my_script")
    end

    it "sets a namespace to the class" do
      expect(Scripts::MyDefaults.namespace).to eq("default")
    end
  end

  describe "#group" do
    it "sets a group" do
      expect(MyScript.group).to eq("script")
    end

    it "inherits the group from parent" do
      expect(MyChildScript.group).to eq("script")
    end

    it "defaults to standard if no group is given" do
      expect(Amazing.group).to eq("standard")
    end
  end

  describe "#subclasses" do
    it "tracks its subclasses in an Array" do
      expect(Thor::Base.subclasses).to include(MyScript)
      expect(Thor::Base.subclasses).to include(MyChildScript)
      expect(Thor::Base.subclasses).to include(Scripts::MyScript)
    end
  end

  describe "#subclass_files" do
    it "returns tracked subclasses, grouped by the files they come from" do
      thorfile = File.join(File.dirname(__FILE__), "fixtures", "script.thor")
      expect(Thor::Base.subclass_files[File.expand_path(thorfile)]).to eq([
        MyScript, MyScript::AnotherScript, MyChildScript, Barn,
        PackageNameScript, Scripts::MyScript, Scripts::MyDefaults,
        Scripts::ChildDefault, Scripts::Arities
      ])
    end

    it "tracks a single subclass across multiple files" do
      thorfile = File.join(File.dirname(__FILE__), "fixtures", "command.thor")
      expect(Thor::Base.subclass_files[File.expand_path(thorfile)]).to include(Amazing)
      expect(Thor::Base.subclass_files[File.expand_path(__FILE__)]).to include(Amazing)
    end
  end

  describe "#commands" do
    it "returns a list with all commands defined in this class" do
      expect(MyChildScript.new).to respond_to("animal")
      expect(MyChildScript.commands.keys).to include("animal")
    end

    it "raises an error if a command with reserved word is defined" do
      expect do
        klass = Class.new(Thor::Group)
        klass.class_eval "def shell; end"
      end.to raise_error(RuntimeError, /"shell" is a Thor reserved word and cannot be defined as command/)
    end
  end

  describe "#all_commands" do
    it "returns a list with all commands defined in this class plus superclasses" do
      expect(MyChildScript.new).to respond_to("foo")
      expect(MyChildScript.all_commands.keys).to include("foo")
    end
  end

  describe "#remove_command" do
    it "removes the command from its commands hash" do
      expect(MyChildScript.all_commands.keys).not_to include("name_with_dashes")
      expect(MyChildScript.commands.keys).not_to include("boom")
    end

    it "undefines the method if desired" do
      expect(MyChildScript.new).not_to respond_to("boom")
    end
  end

  describe "#from_superclass" do
    it "does not send a method to the superclass if the superclass does not respond to it" do
      expect(MyCounter.get_from_super).to eq(13)
    end
  end

  describe "#start" do
    it "raises an error instead of rescuing if THOR_DEBUG=1 is given" do
      begin
        ENV["THOR_DEBUG"] = "1"

        expect do
          MyScript.start %w(what --debug)
        end.to raise_error(Thor::UndefinedCommandError, 'Could not find command "what" in "my_script" namespace.')
      ensure
        ENV["THOR_DEBUG"] = nil
      end
    end

    it "raises an error instead of rescuing if :debug option is given" do
      expect do
        MyScript.start %w(what), :debug => true
      end.to raise_error(Thor::UndefinedCommandError, 'Could not find command "what" in "my_script" namespace.')
    end

    it "suggests commands that are similar if there is a typo" do
      expected = "Could not find command \"paintz\" in \"barn\" namespace.\n"
      expected << "Did you mean?  \"paint\"\n" if Thor::Correctable

      expect(capture(:stderr) { Barn.start(%w(paintz)) }).to eq(expected)
    end

    it "does not steal args" do
      args = %w(foo bar --force true)
      MyScript.start(args)
      expect(args).to eq(%w(foo bar --force true))
    end

    it "checks unknown options" do
      expect(capture(:stderr) do
        MyScript.start(%w(foo bar --force true --unknown baz))
      end.strip).to eq("Unknown switches \"--unknown\"")
    end

    it "checks unknown options except specified" do
      expect(capture(:stderr) do
        expect(MyScript.start(%w(with_optional NAME --omg --invalid))).to eq(["NAME", {}, %w(--omg --invalid)])
      end.strip).to be_empty
    end
  end

  describe "attr_*" do
    it "does not add attr_reader as a command" do
      expect(capture(:stderr) { MyScript.start(%w(another_attribute)) }).to match(/Could not find/)
    end

    it "does not add attr_writer as a command" do
      expect(capture(:stderr) { MyScript.start(%w(another_attribute= foo)) }).to match(/Could not find/)
    end

    it "does not add attr_accessor as a command" do
      expect(capture(:stderr) { MyScript.start(["some_attribute"]) }).to match(/Could not find/)
      expect(capture(:stderr) { MyScript.start(["some_attribute=", "foo"]) }).to match(/Could not find/)
    end
  end
end