ronin 1.4.1 → 1.5.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/.gitignore +1 -0
- data/ChangeLog.md +38 -1
- data/Gemfile +10 -10
- data/README.md +1 -1
- data/Rakefile +13 -2
- data/bin/ronin-net-proxy +25 -0
- data/gemspec.yml +21 -2
- data/lib/bond/completions/ronin.rb +16 -5
- data/lib/ronin/arch.rb +5 -5
- data/lib/ronin/auto_load.rb +22 -1
- data/lib/ronin/campaign.rb +1 -1
- data/lib/ronin/database/database.rb +36 -25
- data/lib/ronin/installation.rb +2 -2
- data/lib/ronin/model/model.rb +5 -6
- data/lib/ronin/model/types/description.rb +0 -3
- data/lib/ronin/os.rb +2 -2
- data/lib/ronin/password.rb +1 -1
- data/lib/ronin/repository.rb +6 -6
- data/lib/ronin/script/path.rb +1 -2
- data/lib/ronin/spec/database.rb +16 -4
- data/lib/ronin/ui/cli/cli.rb +1 -1
- data/lib/ronin/ui/cli/command.rb +50 -7
- data/lib/ronin/ui/cli/commands/console.rb +15 -6
- data/lib/ronin/ui/cli/commands/creds.rb +1 -1
- data/lib/ronin/ui/cli/commands/database.rb +41 -29
- data/lib/ronin/ui/cli/commands/emails.rb +20 -15
- data/lib/ronin/ui/cli/commands/help.rb +18 -5
- data/lib/ronin/ui/cli/commands/hosts.rb +34 -27
- data/lib/ronin/ui/cli/commands/install.rb +21 -4
- data/lib/ronin/ui/cli/commands/ips.rb +34 -23
- data/lib/ronin/ui/cli/commands/net/proxy.rb +403 -0
- data/lib/ronin/ui/cli/commands/repos.rb +4 -4
- data/lib/ronin/ui/cli/commands/uninstall.rb +10 -0
- data/lib/ronin/ui/cli/commands/update.rb +11 -1
- data/lib/ronin/ui/cli/commands/urls.rb +39 -30
- data/lib/ronin/ui/cli/commands/wordlist.rb +11 -1
- data/lib/ronin/ui/console.rb +1 -0
- data/lib/ronin/ui/console/commands.rb +16 -98
- data/lib/ronin/ui/console/shell.rb +184 -0
- data/lib/ronin/url.rb +3 -3
- data/lib/ronin/url_scheme.rb +3 -3
- data/lib/ronin/version.rb +1 -1
- data/man/ronin-campaigns.1.md +78 -0
- data/man/ronin-console.1.md +72 -0
- data/man/ronin-creds.1.md +66 -0
- data/man/ronin-database.1.md +82 -0
- data/man/ronin-emails.1.md +72 -0
- data/man/ronin-exec.1.md +49 -0
- data/man/ronin-help.1.md +34 -0
- data/man/ronin-hosts.1.md +78 -0
- data/man/ronin-install.1.md +79 -0
- data/man/ronin-ips.1.md +81 -0
- data/man/ronin-net-proxy.1.md +86 -0
- data/man/ronin-repos.1.md +77 -0
- data/man/ronin-uninstall.1.md +67 -0
- data/man/ronin-update.1.md +67 -0
- data/man/ronin-urls.1.md +84 -0
- data/man/ronin-wordlist.1.md +53 -0
- data/man/ronin.1.md +26 -0
- data/ronin.gemspec +38 -109
- data/spec/installation_spec.rb +2 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/ui/cli/classes/test_command.rb +7 -0
- data/spec/ui/cli/command_spec.rb +235 -7
- metadata +217 -96
@@ -0,0 +1,67 @@
|
|
1
|
+
# ronin-update 1 "April 2012" Ronin "User Manuals"
|
2
|
+
|
3
|
+
## SYNOPSIS
|
4
|
+
|
5
|
+
`ronin update` [*options*] [*REPO*]
|
6
|
+
|
7
|
+
## DESCRIPTION
|
8
|
+
|
9
|
+
Updates Ronin Repositories.
|
10
|
+
|
11
|
+
## ARGUMENTS
|
12
|
+
|
13
|
+
*REPO*
|
14
|
+
The name of the Repository to update.
|
15
|
+
|
16
|
+
## OPTIONS
|
17
|
+
|
18
|
+
`-v`, `--[no-]verbose`
|
19
|
+
Enable verbose output.
|
20
|
+
|
21
|
+
`-q`, `--[no-]quiet`
|
22
|
+
Disable verbose output.
|
23
|
+
|
24
|
+
`--[no-]silent`
|
25
|
+
Silence all output.
|
26
|
+
|
27
|
+
`--[no-]color`
|
28
|
+
Enables color output.
|
29
|
+
|
30
|
+
## EXAMPLES
|
31
|
+
|
32
|
+
`ronin update repo`
|
33
|
+
Updates the repository with with the name `repo`.
|
34
|
+
|
35
|
+
`ronin update repo@github.com`
|
36
|
+
Updates the repository with the name `repo` and from `github.com`.
|
37
|
+
|
38
|
+
## FILES
|
39
|
+
|
40
|
+
*~/.ronin/*
|
41
|
+
Ronin configuration directory.
|
42
|
+
|
43
|
+
*~/.ronin/repos*
|
44
|
+
Installation directory for Ronin Repositories.
|
45
|
+
|
46
|
+
*~/.ronin/database.log*
|
47
|
+
Database log.
|
48
|
+
|
49
|
+
*~/.ronin/database.sqlite3*
|
50
|
+
The default sqlite3 Database file.
|
51
|
+
|
52
|
+
*~/.ronin/database.yml*
|
53
|
+
Optional Database configuration.
|
54
|
+
|
55
|
+
## ENVIRONMENT
|
56
|
+
|
57
|
+
HOME
|
58
|
+
Specifies the home directory of the user. Ronin will search for the `.ronin`
|
59
|
+
configuration directory within the home directory.
|
60
|
+
|
61
|
+
## AUTHOR
|
62
|
+
|
63
|
+
Postmodern <postmodern.mod3@gmail.com>
|
64
|
+
|
65
|
+
## SEE ALSO
|
66
|
+
|
67
|
+
ronin-install(1) ronin-repos(1) ronin-uninstall(1)
|
data/man/ronin-urls.1.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# ronin-urls 1 "April 2012" Ronin "User Manuals"
|
2
|
+
|
3
|
+
## SYNOPSIS
|
4
|
+
|
5
|
+
`ronin urls` [*options*]
|
6
|
+
|
7
|
+
## DESCRIPTION
|
8
|
+
|
9
|
+
Manages URLs.
|
10
|
+
|
11
|
+
## OPTIONS
|
12
|
+
|
13
|
+
`-v`, `--[no-]verbose`
|
14
|
+
Enable verbose output.
|
15
|
+
|
16
|
+
`-q`, `--[no-]quiet`
|
17
|
+
Disable verbose output.
|
18
|
+
|
19
|
+
`--[no-]silent`
|
20
|
+
Silence all output.
|
21
|
+
|
22
|
+
`--[no-]color`
|
23
|
+
Enables color output.
|
24
|
+
|
25
|
+
`-D`, `--database` *URI*
|
26
|
+
The database to URI (`mysql://user:password@host/ronin`).
|
27
|
+
|
28
|
+
`--[no-]csv`
|
29
|
+
CSV output.
|
30
|
+
|
31
|
+
`--[no-]xml`
|
32
|
+
XML output.
|
33
|
+
|
34
|
+
`--[no-]yaml`
|
35
|
+
YAML output.
|
36
|
+
|
37
|
+
`--[no-]json`
|
38
|
+
JSON output.
|
39
|
+
|
40
|
+
`-i`, `--import` *FILE*
|
41
|
+
Imports HostNames from the FILE.
|
42
|
+
|
43
|
+
`--[no-]http`
|
44
|
+
Searches for `http://` URLs.
|
45
|
+
|
46
|
+
`--[no-]https`
|
47
|
+
Searches for `https://` URLs.
|
48
|
+
|
49
|
+
`-H`, `--hosts` *HOST* [...]
|
50
|
+
Searches for URLs with the given HOST name(s).
|
51
|
+
|
52
|
+
`-p`, `--with-ports` *PORT* [...]
|
53
|
+
Searches for URLs associated with the PORT(s).
|
54
|
+
|
55
|
+
`-d`, `--directory` *DIRECTORY*
|
56
|
+
Searches for URLs sharing the DIRECTORY.
|
57
|
+
|
58
|
+
`-q`, `--with-query-param` *NAME* [...]
|
59
|
+
Searches for URLs containing the query-param NAME.
|
60
|
+
|
61
|
+
`-Q`, `--with-query-value` *VALUE* [...]
|
62
|
+
Searches for URLs containing the query-param VALUE.
|
63
|
+
|
64
|
+
`-l`, `--[no-]list`
|
65
|
+
Lists the HostNames.
|
66
|
+
|
67
|
+
## FILES
|
68
|
+
|
69
|
+
*~/.ronin/*
|
70
|
+
Ronin configuration directory.
|
71
|
+
|
72
|
+
*~/.ronin/database.log*
|
73
|
+
Database log.
|
74
|
+
|
75
|
+
*~/.ronin/database.sqlite3*
|
76
|
+
The default sqlite3 Database file.
|
77
|
+
|
78
|
+
*~/.ronin/database.yml*
|
79
|
+
Optional Database configuration.
|
80
|
+
|
81
|
+
## AUTHOR
|
82
|
+
|
83
|
+
Postmodern <postmodern.mod3@gmail.com>
|
84
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# ronin-wordlist 1 "April 2012" Ronin "User Manuals"
|
2
|
+
|
3
|
+
## SYNOPSIS
|
4
|
+
|
5
|
+
`ronin wordlist` [*options*] [*TEMPLATE*]
|
6
|
+
|
7
|
+
## DESCRIPTION
|
8
|
+
|
9
|
+
Builds and/or mutates Wordlists.
|
10
|
+
|
11
|
+
## ARGUMENTS
|
12
|
+
|
13
|
+
*TEMPLATE*
|
14
|
+
Options word template to generate the wordlist with (`alpha:7 numeric:1-3`).
|
15
|
+
|
16
|
+
## OPTIONS
|
17
|
+
|
18
|
+
`-v`, `--[no-]verbose`
|
19
|
+
Enable verbose output.
|
20
|
+
|
21
|
+
`-q`, `--[no-]quiet`
|
22
|
+
Disable verbose output.
|
23
|
+
|
24
|
+
`--[no-]silent`
|
25
|
+
Silence all output.
|
26
|
+
|
27
|
+
`--[no-]color`
|
28
|
+
Enables color output.
|
29
|
+
|
30
|
+
`-i`, `--input` *FILE*
|
31
|
+
The input text FILE to parse.
|
32
|
+
|
33
|
+
`-o`, `--output` *PATH*
|
34
|
+
The output PATH to write the wordlist to.
|
35
|
+
|
36
|
+
`-m`, `--mutations` *STRING*:*SUBSTITUTE*
|
37
|
+
Mutations to apply to the words. If STRING is found within a word, it will be
|
38
|
+
replaced with SUBSTITUTE.
|
39
|
+
|
40
|
+
## EXAMPLES
|
41
|
+
|
42
|
+
`ronin wordlist alpha:7 numeric:1-3`
|
43
|
+
Enumerates through every possible word, with each word beginning with seven
|
44
|
+
alphabetic characters and ending in 1-3 numeric characters.
|
45
|
+
|
46
|
+
`ronin wordlist --input text.txt -m e:3 -m a:@ -m o:0`
|
47
|
+
Builds a wordlist from a text file, applying basic "leet-speak" mutation rules
|
48
|
+
to each word.
|
49
|
+
|
50
|
+
## AUTHOR
|
51
|
+
|
52
|
+
Postmodern <postmodern.mod3@gmail.com>
|
53
|
+
|
data/man/ronin.1.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# ronin 1 "April 2012" Ronin "User Manuals"
|
2
|
+
|
3
|
+
## SYNOPSIS
|
4
|
+
|
5
|
+
`ronin` [*COMMAND*] [*options*]
|
6
|
+
|
7
|
+
## DESCRIPTION
|
8
|
+
|
9
|
+
Runs a Ronin COMMAND or the starts Ronin Console.
|
10
|
+
|
11
|
+
## ARGUMENTS
|
12
|
+
|
13
|
+
*COMMAND*
|
14
|
+
The Ronin command to execute.
|
15
|
+
|
16
|
+
## OPTIONS
|
17
|
+
|
18
|
+
Additional options for the COMMAND or the Ronin Console.
|
19
|
+
|
20
|
+
## AUTHOR
|
21
|
+
|
22
|
+
Postmodern <postmodern.mod3@gmail.com>
|
23
|
+
|
24
|
+
## SEE ALSO
|
25
|
+
|
26
|
+
ronin-console(1)
|
data/ronin.gemspec
CHANGED
@@ -2,130 +2,59 @@
|
|
2
2
|
|
3
3
|
require 'yaml'
|
4
4
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
lib_dir = File.join(root,'lib')
|
8
|
-
files = if File.directory?('.git')
|
9
|
-
`git ls-files`.split($/)
|
10
|
-
elsif File.directory?('.hg')
|
11
|
-
`hg manifest`.split($/)
|
12
|
-
elsif File.directory?('.svn')
|
13
|
-
`svn ls -R`.split($/).select { |path| File.file?(path) }
|
14
|
-
else
|
15
|
-
Dir['{**/}{.*,*}'].select { |path| File.file?(path) }
|
16
|
-
end
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gemspec = YAML.load_file('gemspec.yml')
|
17
7
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
when String
|
23
|
-
(files & Dir[paths])
|
24
|
-
end
|
25
|
-
}
|
26
|
-
|
27
|
-
version = {
|
28
|
-
:file => 'ronin/version',
|
29
|
-
:constant => 'Ronin::VERSION'
|
30
|
-
}
|
31
|
-
|
32
|
-
defaults = {
|
33
|
-
'name' => File.basename(root),
|
34
|
-
'files' => files,
|
35
|
-
'executables' => filter_files['bin/*'].map { |path| File.basename(path) },
|
36
|
-
'test_files' => filter_files['{test/{**/}*_test.rb,spec/{**/}*_spec.rb}'],
|
37
|
-
'extra_doc_files' => filter_files['*.{txt,rdoc,md,markdown,tt,textile}'],
|
38
|
-
}
|
8
|
+
gem.name = gemspec.fetch('name')
|
9
|
+
gem.version = gemspec.fetch('version') do
|
10
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
39
12
|
|
40
|
-
|
13
|
+
require 'ronin/version'
|
14
|
+
Ronin::VERSION
|
15
|
+
end
|
41
16
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
17
|
+
gem.summary = gemspec['summary']
|
18
|
+
gem.description = gemspec['description']
|
19
|
+
gem.licenses = Array(gemspec['license'])
|
20
|
+
gem.authors = Array(gemspec['authors'])
|
21
|
+
gem.email = gemspec['email']
|
22
|
+
gem.homepage = gemspec['homepage']
|
47
23
|
|
48
|
-
|
49
|
-
eval(version[:constant])
|
50
|
-
end
|
24
|
+
glob = lambda { |patterns| gem.files & Dir[*patterns] }
|
51
25
|
|
52
|
-
|
53
|
-
|
26
|
+
gem.files = `git ls-files`.split($/)
|
27
|
+
gem.files = glob[gemspec['files']] if gemspec['files']
|
54
28
|
|
55
|
-
|
56
|
-
|
57
|
-
gemspec.licenses = metadata['license']
|
58
|
-
when String
|
59
|
-
gemspec.license = metadata['license']
|
29
|
+
gem.executables = gemspec.fetch('executables') do
|
30
|
+
glob['bin/*'].map { |path| File.basename(path) }
|
60
31
|
end
|
32
|
+
gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
|
61
33
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
when String
|
66
|
-
gemspec.author = metadata['authors']
|
67
|
-
end
|
68
|
-
|
69
|
-
gemspec.email = metadata['email']
|
70
|
-
gemspec.homepage = metadata['homepage']
|
34
|
+
gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
|
35
|
+
gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
|
36
|
+
gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
|
71
37
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
when String
|
76
|
-
gemspec.require_path = metadata['require_paths']
|
77
|
-
end
|
38
|
+
gem.require_paths = Array(gemspec.fetch('require_paths') {
|
39
|
+
%w[ext lib].select { |dir| File.directory?(dir) }
|
40
|
+
})
|
78
41
|
|
79
|
-
|
42
|
+
gem.requirements = gemspec['requirements']
|
43
|
+
gem.required_ruby_version = gemspec['required_ruby_version']
|
44
|
+
gem.required_rubygems_version = gemspec['required_rubygems_version']
|
45
|
+
gem.post_install_message = gemspec['post_install_message']
|
80
46
|
|
81
|
-
|
82
|
-
gemspec.extensions = metadata['extensions']
|
83
|
-
|
84
|
-
if Gem::VERSION < '1.7.'
|
85
|
-
gemspec.default_executable = gemspec.executables.first
|
86
|
-
end
|
87
|
-
|
88
|
-
gemspec.test_files = filter_files[metadata['test_files']]
|
89
|
-
|
90
|
-
unless gemspec.files.include?('.document')
|
91
|
-
gemspec.extra_rdoc_files = metadata['extra_doc_files']
|
92
|
-
end
|
93
|
-
|
94
|
-
gemspec.post_install_message = metadata['post_install_message']
|
95
|
-
gemspec.requirements = metadata['requirements']
|
96
|
-
|
97
|
-
if gemspec.respond_to?(:required_ruby_version=)
|
98
|
-
gemspec.required_ruby_version = metadata['required_ruby_version']
|
99
|
-
end
|
100
|
-
|
101
|
-
if gemspec.respond_to?(:required_rubygems_version=)
|
102
|
-
gemspec.required_rubygems_version = metadata['required_rubygems_version']
|
103
|
-
end
|
104
|
-
|
105
|
-
parse_versions = lambda { |versions|
|
106
|
-
case versions
|
107
|
-
when Array
|
108
|
-
versions.map { |v| v.to_s }
|
109
|
-
when String
|
110
|
-
versions.split(/,\s*/)
|
111
|
-
end
|
112
|
-
}
|
113
|
-
|
114
|
-
if metadata['dependencies']
|
115
|
-
metadata['dependencies'].each do |name,versions|
|
116
|
-
gemspec.add_dependency(name,parse_versions[versions])
|
117
|
-
end
|
118
|
-
end
|
47
|
+
split = lambda { |string| string.split(/,\s*/) }
|
119
48
|
|
120
|
-
if
|
121
|
-
|
122
|
-
|
49
|
+
if gemspec['dependencies']
|
50
|
+
gemspec['dependencies'].each do |name,versions|
|
51
|
+
gem.add_dependency(name,split[versions])
|
123
52
|
end
|
124
53
|
end
|
125
54
|
|
126
|
-
if
|
127
|
-
|
128
|
-
|
55
|
+
if gemspec['development_dependencies']
|
56
|
+
gemspec['development_dependencies'].each do |name,versions|
|
57
|
+
gem.add_development_dependency(name,split[versions])
|
129
58
|
end
|
130
59
|
end
|
131
60
|
end
|
data/spec/installation_spec.rb
CHANGED
@@ -23,6 +23,7 @@ describe Installation do
|
|
23
23
|
hosts.rb
|
24
24
|
install.rb
|
25
25
|
ips.rb
|
26
|
+
net/proxy.rb
|
26
27
|
repos.rb
|
27
28
|
update.rb
|
28
29
|
urls.rb
|
@@ -32,7 +33,7 @@ describe Installation do
|
|
32
33
|
}
|
33
34
|
|
34
35
|
describe "each_file" do
|
35
|
-
let(:pattern) { File.join(directory,'*.rb') }
|
36
|
+
let(:pattern) { File.join(directory,'**','*.rb') }
|
36
37
|
let(:expected) { files.map { |name| File.join(directory,name) } }
|
37
38
|
|
38
39
|
it "should enumerate over the files which match a glob pattern" do
|
data/spec/spec_helper.rb
CHANGED
@@ -6,9 +6,11 @@ require 'model/models/described_model'
|
|
6
6
|
require 'model/models/licensed_model'
|
7
7
|
require 'model/models/named_model'
|
8
8
|
require 'model/models/titled_model'
|
9
|
+
require 'classes/my_script'
|
9
10
|
require 'helpers/repositories'
|
10
11
|
|
11
12
|
require 'ronin/spec/database'
|
13
|
+
require 'ronin/spec/ui/output'
|
12
14
|
|
13
15
|
include Ronin
|
14
16
|
|
data/spec/ui/cli/command_spec.rb
CHANGED
@@ -6,8 +6,241 @@ require 'ui/cli/classes/test_command'
|
|
6
6
|
describe UI::CLI::Command do
|
7
7
|
subject { TestCommand }
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
describe "command_name" do
|
10
|
+
it "should be derived from the Class name" do
|
11
|
+
subject.command_name.should == 'test_command'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "usage" do
|
16
|
+
context "without an argument" do
|
17
|
+
it "should return the set usage" do
|
18
|
+
subject.usage.should == '[options] PATH FILE [..]'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with an argument" do
|
23
|
+
let(:expected) { 'FOO' }
|
24
|
+
|
25
|
+
subject { Class.new(described_class) }
|
26
|
+
before { subject.usage expected }
|
27
|
+
|
28
|
+
it "should set the usage" do
|
29
|
+
subject.usage.should == expected
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "default" do
|
34
|
+
subject { Class.new(described_class).usage }
|
35
|
+
|
36
|
+
it { should == '[options]' }
|
37
|
+
end
|
38
|
+
|
39
|
+
context "inherited" do
|
40
|
+
let(:superclass) { TestCommand }
|
41
|
+
|
42
|
+
subject { Class.new(superclass).usage }
|
43
|
+
|
44
|
+
it "should default to the usage of the superclass" do
|
45
|
+
subject.should == superclass.usage
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "summary" do
|
51
|
+
context "without an argument" do
|
52
|
+
it "should return the set summary" do
|
53
|
+
subject.summary.should == 'Tests the default task'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with an argument" do
|
58
|
+
let(:expected) { 'Performs foo' }
|
59
|
+
|
60
|
+
subject { Class.new(described_class) }
|
61
|
+
before { subject.summary expected }
|
62
|
+
|
63
|
+
it "should set the usage" do
|
64
|
+
subject.summary.should == expected
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "default" do
|
69
|
+
subject { Class.new(described_class).summary }
|
70
|
+
|
71
|
+
it { should == nil }
|
72
|
+
end
|
73
|
+
|
74
|
+
context "inherited" do
|
75
|
+
let(:superclass) { TestCommand }
|
76
|
+
|
77
|
+
subject { Class.new(superclass).summary }
|
78
|
+
|
79
|
+
it "should default to the summary of the superclass" do
|
80
|
+
subject.should == superclass.summary
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "examples" do
|
86
|
+
context "without an argument" do
|
87
|
+
it "should return the set summary" do
|
88
|
+
# subject.example.should == 'Tests the default task'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with an argument" do
|
93
|
+
let(:expected) do
|
94
|
+
['test_command --foo PATH', 'test_command --foo PATH FILE ...']
|
95
|
+
end
|
96
|
+
|
97
|
+
subject { Class.new(described_class) }
|
98
|
+
before { subject.examples expected }
|
99
|
+
|
100
|
+
it "should set the usage" do
|
101
|
+
subject.examples.should == expected
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "default" do
|
106
|
+
subject { Class.new(described_class).examples }
|
107
|
+
|
108
|
+
it { should == [] }
|
109
|
+
end
|
110
|
+
|
111
|
+
context "inherited" do
|
112
|
+
let(:superclass) { TestCommand }
|
113
|
+
|
114
|
+
subject { Class.new(superclass).examples }
|
115
|
+
|
116
|
+
it "should default to the examples of the superclass" do
|
117
|
+
subject.should == superclass.examples
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "options" do
|
123
|
+
subject { Class.new(described_class).options }
|
124
|
+
|
125
|
+
context "inherited" do
|
126
|
+
it "should be {} by default" do
|
127
|
+
subject.should == {}
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context described_class do
|
132
|
+
subject { described_class.options }
|
133
|
+
|
134
|
+
it "should have a :verbose option" do
|
135
|
+
subject.should have_key(:verbose)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should have a :quiet option" do
|
139
|
+
subject.should have_key(:quiet)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should have a :silent option" do
|
143
|
+
subject.should have_key(:silent)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should have a :color option" do
|
147
|
+
subject.should have_key(:color)
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "color option" do
|
151
|
+
subject { described_class.new.color }
|
152
|
+
|
153
|
+
context "when $stdout is a TTY" do
|
154
|
+
it { should be_true }
|
155
|
+
end
|
156
|
+
|
157
|
+
context "when $stdout is not a TTY" do
|
158
|
+
before do
|
159
|
+
@old_stdout = $stdout
|
160
|
+
$stdout = StringIO.new
|
161
|
+
end
|
162
|
+
|
163
|
+
it { should be_false }
|
164
|
+
|
165
|
+
after do
|
166
|
+
$stdout = @old_stdout
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "option" do
|
174
|
+
let(:name) { :foo }
|
175
|
+
|
176
|
+
it "should define an option" do
|
177
|
+
subject.options[name].should be_kind_of(Hash)
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should define a parameter" do
|
181
|
+
subject.should have_param(name)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "each_option" do
|
186
|
+
let(:expected) { [:verbose, :quiet, :silent, :color, :foo] }
|
187
|
+
|
188
|
+
it "should iterate over each option" do
|
189
|
+
names = []
|
190
|
+
|
191
|
+
subject.each_option do |name,options|
|
192
|
+
names << name
|
193
|
+
end
|
194
|
+
|
195
|
+
names.should =~ expected
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
describe "options?" do
|
200
|
+
it "should test if there are any defined options" do
|
201
|
+
subject.options?.should be_true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "arguments" do
|
206
|
+
context "inherited" do
|
207
|
+
subject { Class.new(described_class).arguments }
|
208
|
+
|
209
|
+
it { should == [] }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "argument" do
|
214
|
+
let(:name) { :foo }
|
215
|
+
|
216
|
+
subject { Class.new(described_class) }
|
217
|
+
before { subject.argument name }
|
218
|
+
|
219
|
+
it "should add to arguments" do
|
220
|
+
subject.arguments.should include(name)
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should define a parameter" do
|
224
|
+
subject.should have_param(name)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "each_argument" do
|
229
|
+
let(:expected) { [:path, :files] }
|
230
|
+
|
231
|
+
it "should iterate over each option" do
|
232
|
+
names = []
|
233
|
+
|
234
|
+
subject.each_argument { |name| names << name }
|
235
|
+
|
236
|
+
names.should =~ expected
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
describe "arguments?" do
|
241
|
+
it "should test if there are any defined arguments" do
|
242
|
+
subject.arguments?.should be_true
|
243
|
+
end
|
11
244
|
end
|
12
245
|
|
13
246
|
describe "#run" do
|
@@ -51,9 +284,4 @@ describe UI::CLI::Command do
|
|
51
284
|
subject.files.should == files
|
52
285
|
end
|
53
286
|
end
|
54
|
-
|
55
|
-
it "should have zero indentation by default" do
|
56
|
-
command = subject.new
|
57
|
-
command.instance_variable_get('@indent').should == 0
|
58
|
-
end
|
59
287
|
end
|