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.
- checksums.yaml +7 -0
- data/.document +3 -0
- data/.github/workflows/ruby.yml +29 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +29 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +20 -0
- data/README.md +283 -0
- data/Rakefile +23 -0
- data/command_kit.gemspec +60 -0
- data/gemspec.yml +14 -0
- data/lib/command_kit.rb +1 -0
- data/lib/command_kit/arguments.rb +161 -0
- data/lib/command_kit/arguments/argument.rb +111 -0
- data/lib/command_kit/arguments/argument_value.rb +81 -0
- data/lib/command_kit/arguments/usage.rb +6 -0
- data/lib/command_kit/colors.rb +355 -0
- data/lib/command_kit/command.rb +42 -0
- data/lib/command_kit/command_name.rb +95 -0
- data/lib/command_kit/commands.rb +299 -0
- data/lib/command_kit/commands/auto_load.rb +153 -0
- data/lib/command_kit/commands/auto_load/subcommand.rb +90 -0
- data/lib/command_kit/commands/auto_require.rb +138 -0
- data/lib/command_kit/commands/command.rb +12 -0
- data/lib/command_kit/commands/help.rb +43 -0
- data/lib/command_kit/commands/parent_command.rb +21 -0
- data/lib/command_kit/commands/subcommand.rb +51 -0
- data/lib/command_kit/console.rb +141 -0
- data/lib/command_kit/description.rb +89 -0
- data/lib/command_kit/env.rb +43 -0
- data/lib/command_kit/env/home.rb +71 -0
- data/lib/command_kit/env/path.rb +71 -0
- data/lib/command_kit/examples.rb +99 -0
- data/lib/command_kit/exception_handler.rb +55 -0
- data/lib/command_kit/help.rb +62 -0
- data/lib/command_kit/help/man.rb +125 -0
- data/lib/command_kit/inflector.rb +84 -0
- data/lib/command_kit/main.rb +103 -0
- data/lib/command_kit/options.rb +179 -0
- data/lib/command_kit/options/option.rb +171 -0
- data/lib/command_kit/options/option_value.rb +90 -0
- data/lib/command_kit/options/parser.rb +227 -0
- data/lib/command_kit/options/quiet.rb +53 -0
- data/lib/command_kit/options/usage.rb +6 -0
- data/lib/command_kit/options/verbose.rb +55 -0
- data/lib/command_kit/options/version.rb +62 -0
- data/lib/command_kit/os.rb +47 -0
- data/lib/command_kit/pager.rb +115 -0
- data/lib/command_kit/printing.rb +32 -0
- data/lib/command_kit/printing/indent.rb +78 -0
- data/lib/command_kit/program_name.rb +57 -0
- data/lib/command_kit/stdio.rb +138 -0
- data/lib/command_kit/usage.rb +102 -0
- data/lib/command_kit/version.rb +4 -0
- data/lib/command_kit/xdg.rb +138 -0
- data/spec/arguments/argument_spec.rb +169 -0
- data/spec/arguments/argument_value_spec.rb +126 -0
- data/spec/arguments_spec.rb +213 -0
- data/spec/colors_spec.rb +470 -0
- data/spec/command_kit_spec.rb +8 -0
- data/spec/command_name_spec.rb +130 -0
- data/spec/command_spec.rb +49 -0
- data/spec/commands/auto_load/subcommand_spec.rb +82 -0
- data/spec/commands/auto_load_spec.rb +128 -0
- data/spec/commands/auto_require_spec.rb +142 -0
- data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +10 -0
- data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +10 -0
- data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +10 -0
- data/spec/commands/help_spec.rb +66 -0
- data/spec/commands/parent_command_spec.rb +40 -0
- data/spec/commands/subcommand_spec.rb +99 -0
- data/spec/commands_spec.rb +767 -0
- data/spec/console_spec.rb +201 -0
- data/spec/description_spec.rb +203 -0
- data/spec/env/home_spec.rb +46 -0
- data/spec/env/path_spec.rb +78 -0
- data/spec/env_spec.rb +123 -0
- data/spec/examples_spec.rb +235 -0
- data/spec/exception_handler_spec.rb +103 -0
- data/spec/help_spec.rb +119 -0
- data/spec/inflector_spec.rb +104 -0
- data/spec/main_spec.rb +179 -0
- data/spec/options/option_spec.rb +258 -0
- data/spec/options/option_value_spec.rb +67 -0
- data/spec/options/parser_spec.rb +265 -0
- data/spec/options_spec.rb +137 -0
- data/spec/os_spec.rb +46 -0
- data/spec/pager_spec.rb +154 -0
- data/spec/printing/indent_spec.rb +130 -0
- data/spec/printing_spec.rb +76 -0
- data/spec/program_name_spec.rb +62 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/stdio_spec.rb +264 -0
- data/spec/usage_spec.rb +237 -0
- data/spec/xdg_spec.rb +191 -0
- metadata +156 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'command_kit/command_name'
|
|
3
|
+
|
|
4
|
+
describe CommandName do
|
|
5
|
+
module TestCommandName
|
|
6
|
+
class ImplicitCmd
|
|
7
|
+
include CommandKit::CommandName
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
let(:command_class) { TestCommandName::ImplicitCmd }
|
|
12
|
+
|
|
13
|
+
describe ".command_name" do
|
|
14
|
+
subject { command_class }
|
|
15
|
+
|
|
16
|
+
context "when no command_name has been set" do
|
|
17
|
+
it "should underscore the class'es name" do
|
|
18
|
+
expect(subject.command_name).to eq('implicit_cmd')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when a command_name is explicitly set" do
|
|
23
|
+
module TestCommandName
|
|
24
|
+
class ExplicitCmd
|
|
25
|
+
include CommandKit::CommandName
|
|
26
|
+
command_name 'explicit'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
subject { TestCommandName::ExplicitCmd }
|
|
31
|
+
|
|
32
|
+
it "must return the explicitly set command_name" do
|
|
33
|
+
expect(subject.command_name).to eq('explicit')
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
context "when the command class inherites from another class" do
|
|
38
|
+
module TestCommandName
|
|
39
|
+
class BaseCmd
|
|
40
|
+
include CommandKit::CommandName
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class InheritedCmd < BaseCmd
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
subject { TestCommandName::InheritedCmd }
|
|
48
|
+
|
|
49
|
+
it "should underscore the class'es name" do
|
|
50
|
+
expect(subject.command_name).to eq('inherited_cmd')
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context "when the superclass defines an explicit command_name" do
|
|
54
|
+
module TestCommandName
|
|
55
|
+
class ExplicitBaseCmd
|
|
56
|
+
include CommandKit::CommandName
|
|
57
|
+
command_name :explicit
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class ImplicitInheritedCmd < ExplicitBaseCmd
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
let(:super_subject) { TestCommandName::ExplicitBaseCmd }
|
|
65
|
+
subject { TestCommandName::ImplicitInheritedCmd }
|
|
66
|
+
|
|
67
|
+
it "must return the subclass'es command_name, not the superclass'es" do
|
|
68
|
+
expect(subject.command_name).to eq('implicit_inherited_cmd')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "must not change the superclass'es command_name" do
|
|
72
|
+
expect(super_subject.command_name).to eq('explicit')
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when the subclass defines an explicit command_name" do
|
|
77
|
+
module TestCommandName
|
|
78
|
+
class ImplicitBaseCmd
|
|
79
|
+
include CommandKit::CommandName
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class ExplicitInheritedCmd < ImplicitBaseCmd
|
|
83
|
+
command_name :explicit
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
let(:super_subject) { TestCommandName::ImplicitBaseCmd }
|
|
88
|
+
subject { TestCommandName::ExplicitInheritedCmd }
|
|
89
|
+
|
|
90
|
+
it "must return the subclass'es command_name, not the superclass'es" do
|
|
91
|
+
expect(subject.command_name).to eq('explicit')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "must not change the superclass'es command_name" do
|
|
95
|
+
expect(super_subject.command_name).to eq('implicit_base_cmd')
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "#initialize" do
|
|
102
|
+
context "when given no keyword arguments" do
|
|
103
|
+
subject { command_class.new }
|
|
104
|
+
|
|
105
|
+
it "must set #command_name to .command_name" do
|
|
106
|
+
expect(subject.command_name).to eq(command_class.command_name)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
context "when given the command_name: keyword argument" do
|
|
111
|
+
let(:command_name) { 'foo' }
|
|
112
|
+
|
|
113
|
+
subject { command_class.new(command_name: command_name) }
|
|
114
|
+
|
|
115
|
+
it "must set #command_name to the command_name: keyword argument" do
|
|
116
|
+
expect(subject.command_name).to eq(command_name)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe "#command_name" do
|
|
122
|
+
let(:command_name) { 'foo' }
|
|
123
|
+
|
|
124
|
+
subject { command_class.new(command_name: command_name) }
|
|
125
|
+
|
|
126
|
+
it "must return the initialized command_name: value" do
|
|
127
|
+
expect(subject.command_name).to eq(command_name)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'command_kit/command'
|
|
3
|
+
|
|
4
|
+
describe Command do
|
|
5
|
+
it "must include CommandKit::Main" do
|
|
6
|
+
expect(described_class).to include(CommandKit::Main)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "must include CommandKit::Env" do
|
|
10
|
+
expect(described_class).to include(CommandKit::Env)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "must include CommandKit::Stdio" do
|
|
14
|
+
expect(described_class).to include(CommandKit::Stdio)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "must include CommandKit::Printing" do
|
|
18
|
+
expect(described_class).to include(CommandKit::Printing)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "must include CommandKit::Help" do
|
|
22
|
+
expect(described_class).to include(CommandKit::Help)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "must include CommandKit::Usage" do
|
|
26
|
+
expect(described_class).to include(CommandKit::Usage)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "must include CommandKit::Arguments" do
|
|
30
|
+
expect(described_class).to include(CommandKit::Arguments)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "must include CommandKit::Options" do
|
|
34
|
+
expect(described_class).to include(CommandKit::Options)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "must include CommandKit::Examples" do
|
|
38
|
+
expect(described_class).to include(CommandKit::Examples)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "must include CommandKit::Description" do
|
|
42
|
+
expect(described_class).to include(CommandKit::Description)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "must include CommandKit::ExceptionHandler" do
|
|
46
|
+
expect(described_class).to include(CommandKit::ExceptionHandler)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'command_kit/commands/auto_load/subcommand'
|
|
3
|
+
|
|
4
|
+
describe Commands::AutoLoad::Subcommand do
|
|
5
|
+
let(:fixtures_dir) { File.expand_path('../../fixtures',__FILE__) }
|
|
6
|
+
|
|
7
|
+
let(:file) { 'test1.rb' }
|
|
8
|
+
let(:path) { File.join(fixtures_dir,'test_auto_load/cli/commands',file) }
|
|
9
|
+
|
|
10
|
+
let(:class_name) { 'Test1' }
|
|
11
|
+
let(:constant) { "TestAutoLoad::CLI::Commands::#{class_name}" }
|
|
12
|
+
|
|
13
|
+
subject { described_class.new(constant,path) }
|
|
14
|
+
|
|
15
|
+
describe "#initialize" do
|
|
16
|
+
it "must set #constant" do
|
|
17
|
+
expect(subject.constant).to eq(constant)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "must set #path" do
|
|
21
|
+
expect(subject.path).to eq(path)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "when an explicit summary: option is given" do
|
|
25
|
+
let(:summary) { 'This is a test' }
|
|
26
|
+
|
|
27
|
+
subject { described_class.new(constant,path, summary: summary) }
|
|
28
|
+
|
|
29
|
+
it "must set #summary" do
|
|
30
|
+
expect(subject.summary).to eq(summary)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#require!" do
|
|
36
|
+
it "must require #path" do
|
|
37
|
+
expect($LOADED_FEATURES).to_not include(path)
|
|
38
|
+
|
|
39
|
+
subject.require!
|
|
40
|
+
|
|
41
|
+
expect($LOADED_FEATURES).to include(path)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "when #path does not exist" do
|
|
45
|
+
let(:path) { '/does/not/exist' }
|
|
46
|
+
|
|
47
|
+
it do
|
|
48
|
+
expect { subject.require! }.to raise_error(LoadError)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "#const_get" do
|
|
54
|
+
before { subject.require! }
|
|
55
|
+
|
|
56
|
+
it "must resolve #constant" do
|
|
57
|
+
expect(subject.const_get).to eq(TestAutoLoad::CLI::Commands::Test1)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
context "when the constant shadows a global constant" do
|
|
61
|
+
let(:constant) { 'TestAutoLoad::CLI::Commands::Object' }
|
|
62
|
+
|
|
63
|
+
it do
|
|
64
|
+
expect { subject.const_get }.to raise_error(NameError)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "when #constant cannot be found" do
|
|
69
|
+
let(:constant) { 'Does::Not::Exist' }
|
|
70
|
+
|
|
71
|
+
it do
|
|
72
|
+
expect { subject.const_get }.to raise_error(NameError)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "#command" do
|
|
78
|
+
it "return the command class" do
|
|
79
|
+
expect(subject.command).to eq(TestAutoLoad::CLI::Commands::Test1)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'command_kit/commands/auto_load'
|
|
3
|
+
|
|
4
|
+
describe Commands::AutoLoad do
|
|
5
|
+
let(:fixtures_dir) { File.expand_path('../fixtures',__FILE__) }
|
|
6
|
+
|
|
7
|
+
let(:dir) { File.join(fixtures_dir,'test_auto_load','cli','commands') }
|
|
8
|
+
let(:namespace) { 'TestAutoLoad::CLI::Commands' }
|
|
9
|
+
|
|
10
|
+
subject { described_class.new(dir: dir, namespace: namespace) }
|
|
11
|
+
|
|
12
|
+
describe "#initialize" do
|
|
13
|
+
it "must set #dir" do
|
|
14
|
+
expect(subject.dir).to eq(dir)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "must set #namespace" do
|
|
18
|
+
expect(subject.namespace).to eq(namespace)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "must populate #commands based on the files within #dir" do
|
|
22
|
+
expect(subject.commands['test1']).to be_kind_of(described_class::Subcommand)
|
|
23
|
+
expect(subject.commands['test1'].constant).to eq("#{namespace}::Test1")
|
|
24
|
+
expect(subject.commands['test1'].path).to eq(File.join(dir,'test1.rb'))
|
|
25
|
+
|
|
26
|
+
expect(subject.commands['test2']).to be_kind_of(described_class::Subcommand)
|
|
27
|
+
expect(subject.commands['test2'].constant).to eq("#{namespace}::Test2")
|
|
28
|
+
expect(subject.commands['test2'].path).to eq(File.join(dir,'test2.rb'))
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context "when given a block" do
|
|
32
|
+
subject do
|
|
33
|
+
described_class.new(dir: dir, namespace: namespace) do |autoload|
|
|
34
|
+
autoload.command 'test-1', 'Test1', 'test1.rb'
|
|
35
|
+
autoload.command 'test-2', 'Test2', 'test2.rb'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "must not populate #commands based on the files within #dir" do
|
|
40
|
+
expect(subject.commands['test1']).to be(nil)
|
|
41
|
+
expect(subject.commands['test2']).to be(nil)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "must allow explicitly initializing #commands via #command" do
|
|
45
|
+
expect(subject.commands['test-1']).to be_kind_of(described_class::Subcommand)
|
|
46
|
+
expect(subject.commands['test-1'].constant).to eq("#{namespace}::Test1")
|
|
47
|
+
expect(subject.commands['test-1'].path).to eq(File.join(dir,'test1.rb'))
|
|
48
|
+
|
|
49
|
+
expect(subject.commands['test-2']).to be_kind_of(described_class::Subcommand)
|
|
50
|
+
expect(subject.commands['test-2'].constant).to eq("#{namespace}::Test2")
|
|
51
|
+
expect(subject.commands['test-2'].path).to eq(File.join(dir,'test2.rb'))
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
module TestAutoLoad
|
|
57
|
+
class CLI
|
|
58
|
+
include CommandKit::Commands
|
|
59
|
+
include CommandKit::Commands::AutoLoad.new(
|
|
60
|
+
dir: File.expand_path('../fixtures/test_auto_load/cli/commands',__FILE__),
|
|
61
|
+
namespace: "#{self}::Commands"
|
|
62
|
+
)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
let(:command_class) { TestAutoLoad::CLI }
|
|
67
|
+
let(:autoload_module) { command_class.included_modules.first }
|
|
68
|
+
|
|
69
|
+
describe "#included" do
|
|
70
|
+
subject { command_class }
|
|
71
|
+
|
|
72
|
+
it "must also include CommandKit::Commands" do
|
|
73
|
+
expect(subject).to include(CommandKit::Commands)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "must merge the module's #commands into the class'es #commands" do
|
|
77
|
+
expect(command_class.commands).to include(autoload_module.commands)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "#join" do
|
|
82
|
+
let(:path) { 'foo/bar' }
|
|
83
|
+
|
|
84
|
+
it "must join the path with #dir" do
|
|
85
|
+
expect(subject.join(path)).to eq(File.join(dir,path))
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "#files" do
|
|
90
|
+
it "must list the files within the auto-load directory" do
|
|
91
|
+
expect(subject.files).to eq(Dir["#{dir}/*.rb"])
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "#command" do
|
|
96
|
+
let(:command_name) { 'test' }
|
|
97
|
+
let(:constant) { 'Test' }
|
|
98
|
+
let(:file) { 'test.rb' }
|
|
99
|
+
|
|
100
|
+
before do
|
|
101
|
+
subject.command command_name, constant, file
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "must add a Subcommand to #commands with the given command name" do
|
|
105
|
+
expect(subject.commands[command_name]).to be_kind_of(described_class::Subcommand)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "must join the given file: value with #dir" do
|
|
109
|
+
expect(subject.commands[command_name].path).to eq(File.join(dir,file))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "must combine the given constant: value with #namespace" do
|
|
113
|
+
expect(subject.commands[command_name].constant).to eq("#{namespace}::#{constant}")
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "when given a summary: value" do
|
|
117
|
+
let(:summary) { 'Test is a test' }
|
|
118
|
+
|
|
119
|
+
before do
|
|
120
|
+
subject.command command_name, constant, file, summary: summary
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "must set the subcommand's #summary" do
|
|
124
|
+
expect(subject.commands[command_name].summary).to eq(summary)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'command_kit/commands/auto_require'
|
|
3
|
+
|
|
4
|
+
describe Commands::AutoRequire do
|
|
5
|
+
let(:fixtures_dir) { File.expand_path('../fixtures',__FILE__) }
|
|
6
|
+
let(:lib_dir) { File.join(fixtures_dir,'test_auto_require','lib') }
|
|
7
|
+
let(:dir) { File.join('test_auto_require','cli','commands') }
|
|
8
|
+
let(:namespace) { 'TestAutoRequire::CLI::Commands' }
|
|
9
|
+
|
|
10
|
+
before { $LOAD_PATH.unshift(lib_dir) }
|
|
11
|
+
after { $LOAD_PATH.delete(lib_dir) }
|
|
12
|
+
|
|
13
|
+
describe "#initialize" do
|
|
14
|
+
subject { described_class.new(dir: dir, namespace: namespace) }
|
|
15
|
+
|
|
16
|
+
it "must set #dir" do
|
|
17
|
+
expect(subject.dir).to eq(dir)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "must set #namespace" do
|
|
21
|
+
expect(subject.namespace).to eq(namespace)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module TestAutoRequire
|
|
26
|
+
class CLI
|
|
27
|
+
include CommandKit::Commands
|
|
28
|
+
include CommandKit::Commands::AutoRequire.new(
|
|
29
|
+
dir: 'test_auto_require/cli/commands',
|
|
30
|
+
namespace: "#{self}::Commands"
|
|
31
|
+
)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
let(:command_class) { TestAutoRequire::CLI }
|
|
36
|
+
let(:auto_require_module) { command_class.included_modules.first }
|
|
37
|
+
|
|
38
|
+
subject { described_class.new(dir: dir, namespace: namespace) }
|
|
39
|
+
|
|
40
|
+
describe "#join" do
|
|
41
|
+
let(:path) { 'foo/bar' }
|
|
42
|
+
|
|
43
|
+
it "must join the path with #dir" do
|
|
44
|
+
expect(subject.join(path)).to eq(File.join(dir,path))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
let(:file_name) { 'test1' }
|
|
49
|
+
|
|
50
|
+
describe "#require" do
|
|
51
|
+
let(:path) { File.join(lib_dir,dir,"#{file_name}.rb") }
|
|
52
|
+
|
|
53
|
+
it "must require #path" do
|
|
54
|
+
expect($LOADED_FEATURES).to_not include(path)
|
|
55
|
+
|
|
56
|
+
subject.require(file_name)
|
|
57
|
+
|
|
58
|
+
expect($LOADED_FEATURES).to include(path)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when #path does not exist" do
|
|
62
|
+
let(:file_name) { 'does_not_exist' }
|
|
63
|
+
|
|
64
|
+
it do
|
|
65
|
+
expect { subject.require(file_name) }.to raise_error(LoadError)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "#const_get" do
|
|
71
|
+
before { subject.require(file_name) }
|
|
72
|
+
|
|
73
|
+
let(:constant) { 'Test1' }
|
|
74
|
+
|
|
75
|
+
it "must resolve the given constant within the namespace" do
|
|
76
|
+
expect(subject.const_get(constant)).to eq(TestAutoRequire::CLI::Commands::Test1)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "when the constant shadows a global constant" do
|
|
80
|
+
let(:constant) { 'Object' }
|
|
81
|
+
|
|
82
|
+
it do
|
|
83
|
+
expect { subject.const_get(constant) }.to raise_error(NameError)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context "when #constant cannot be found" do
|
|
88
|
+
let(:constant) { 'DoesNotExist' }
|
|
89
|
+
|
|
90
|
+
it do
|
|
91
|
+
expect { subject.const_get(constant) }.to raise_error(NameError)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "#command" do
|
|
97
|
+
let(:command_name) { 'test1' }
|
|
98
|
+
|
|
99
|
+
it "must require the command's file and return the command class" do
|
|
100
|
+
expect(subject.command(command_name)).to eq(TestAutoRequire::CLI::Commands::Test1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "when command's file cannot be found" do
|
|
104
|
+
let(:command_name) { 'does_not_exist' }
|
|
105
|
+
|
|
106
|
+
it do
|
|
107
|
+
expect(subject.command(command_name)).to be(nil)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe "#included" do
|
|
113
|
+
subject { command_class }
|
|
114
|
+
|
|
115
|
+
it "must also include CommandKit::Commands" do
|
|
116
|
+
expect(subject).to include(CommandKit::Commands)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe ".commands" do
|
|
120
|
+
it "must set the class'es .commands.default_proc" do
|
|
121
|
+
expect(command_class.commands.default_proc).to_not be(nil)
|
|
122
|
+
expect(command_class.commands.default_proc).to be_kind_of(Proc)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
let(:command_name) { 'test1' }
|
|
126
|
+
|
|
127
|
+
it "the .commands.default_proc must auto-require commands and return a Subcommand" do
|
|
128
|
+
expect(command_class.commands[command_name]).to_not be(nil)
|
|
129
|
+
expect(command_class.commands[command_name]).to be_kind_of(Commands::Subcommand)
|
|
130
|
+
expect(command_class.commands[command_name].command).to eq(TestAutoRequire::CLI::Commands::Test1)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
context "when the given command_name cannot be auto-required" do
|
|
134
|
+
let(:command_name) { 'does_not_exist' }
|
|
135
|
+
|
|
136
|
+
it do
|
|
137
|
+
expect(command_class.commands[command_name]).to be(nil)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|