maximus 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +23 -5
- data/lib/maximus/cli.rb +8 -4
- data/lib/maximus/config.rb +161 -149
- data/lib/maximus/config/maximus.yml +60 -2
- data/lib/maximus/config/wraith/nojs.js +3 -1
- data/lib/maximus/config/wraith/snap.js +3 -1
- data/lib/maximus/git_control.rb +224 -119
- data/lib/maximus/helper.rb +7 -25
- data/lib/maximus/lint.rb +64 -88
- data/lib/maximus/lints/brakeman.rb +2 -9
- data/lib/maximus/lints/jshint.rb +1 -5
- data/lib/maximus/lints/railsbp.rb +12 -21
- data/lib/maximus/lints/rubocop.rb +1 -5
- data/lib/maximus/lints/scsslint.rb +1 -4
- data/lib/maximus/reporter/git-lines.sh +8 -22
- data/lib/maximus/statistic.rb +2 -2
- data/lib/maximus/statistics/phantomas.rb +0 -1
- data/lib/maximus/statistics/stylestats.rb +91 -56
- data/lib/maximus/statistics/wraith.rb +79 -21
- data/lib/maximus/version.rb +1 -1
- data/maximus.gemspec +8 -8
- data/roadmap.md +4 -0
- data/spec/maximus/config_spec.rb +98 -5
- data/spec/maximus/git_control_spec.rb +172 -0
- data/spec/maximus/helper_spec.rb +97 -0
- data/spec/maximus/lint_spec.rb +51 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/rubocop.yml +1 -0
- metadata +40 -33
- data/lib/maximus/config/rubocop.yml +0 -1007
data/spec/maximus/config_spec.rb
CHANGED
@@ -5,20 +5,21 @@ describe Maximus::Config do
|
|
5
5
|
|
6
6
|
subject(:config) do
|
7
7
|
File.write(config_path, config_body)
|
8
|
-
|
8
|
+
config_contents = config_body.blank? ? {} : { config_file: config_path }
|
9
|
+
described_class.new(config_contents)
|
9
10
|
end
|
10
11
|
|
11
12
|
describe '#is_dev?', :isolated_environment do
|
12
13
|
context 'setting root value is_dev to true' do
|
13
14
|
let(:config_body) { 'is_dev: true' }
|
14
|
-
it '
|
15
|
+
it 'should be true' do
|
15
16
|
expect(config.is_dev?).to be true
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
|
-
context '
|
20
|
+
context 'is blank/not supplied' do
|
20
21
|
let(:config_body) { '' }
|
21
|
-
it '
|
22
|
+
it 'should default to false' do
|
22
23
|
expect(config.is_dev?).to be false
|
23
24
|
end
|
24
25
|
end
|
@@ -33,7 +34,7 @@ describe Maximus::Config do
|
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
context 'not supplying a linter but relying on the default
|
37
|
+
context 'not supplying a linter but relying on the default' do
|
37
38
|
let(:config_body) { '' }
|
38
39
|
it 'should include a linter' do
|
39
40
|
expect(config.settings.has_key?(:scsslint)).to be true
|
@@ -41,4 +42,96 @@ describe Maximus::Config do
|
|
41
42
|
end
|
42
43
|
|
43
44
|
end
|
45
|
+
|
46
|
+
describe '#domain', :isolated_environment do
|
47
|
+
|
48
|
+
context 'domain is provided' do
|
49
|
+
|
50
|
+
context 'without a port' do
|
51
|
+
let(:config_body) { 'domain: http://example.com' }
|
52
|
+
it 'should provide the domain' do
|
53
|
+
expect( config.domain ).to eq 'http://example.com'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with a port' do
|
58
|
+
let(:config_body) { "domain: http://example.com\nport: 8080" }
|
59
|
+
it 'should provide the domain with port attached' do
|
60
|
+
expect( config.domain ).to eq 'http://example.com:8080'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'port is provided' do
|
67
|
+
|
68
|
+
context 'without a domain' do
|
69
|
+
let(:config_body) { 'port: 8080' }
|
70
|
+
it 'should provide the default domain with the port attached' do
|
71
|
+
expect( config.domain ).to eq 'http://localhost:8080'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with a domain' do
|
76
|
+
let(:config_body) { "domain: http://example.com\nport: 8080" }
|
77
|
+
it 'should provide the domain with the port attached' do
|
78
|
+
expect( config.domain ).to eq 'http://example.com:8080'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#split_paths', :isolated_environment do
|
87
|
+
|
88
|
+
context 'an array is provided' do
|
89
|
+
let(:config_body) { "paths: \n - '/'\n - '/about'"}
|
90
|
+
it 'should return the paths with labels' do
|
91
|
+
expect( config.settings[:paths] ).to eq ({ 'home' => '/', 'about' => '/about'})
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'a hash is provided' do
|
96
|
+
let(:config_body) { "paths: \n home: '/'\n about: '/about'"}
|
97
|
+
it 'should return the paths with labels' do
|
98
|
+
expect( config.settings[:paths] ).to eq ({ 'home' => '/', 'about' => '/about'})
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'nothing is provided' do
|
103
|
+
let(:config_body) { '' }
|
104
|
+
it 'should return the default path with label' do
|
105
|
+
expect( config.settings[:paths] ).to eq ({ 'home' => '/'})
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#load_config', :isolated_environment do
|
112
|
+
|
113
|
+
context 'a file path is provided' do
|
114
|
+
let(:config_body) { 'rubocop: spec/support/rubocop.yml' }
|
115
|
+
it 'should load the file' do
|
116
|
+
expect( YAML.load_file(config.settings[:rubocop])['Rubolinter'] ).to be true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'settings are provided' do
|
121
|
+
let(:config_body) { "rubocop:\n Rubolinter: true" }
|
122
|
+
it 'should store the settings appropriately' do
|
123
|
+
expect( YAML.load_file(config.settings[:rubocop])['Rubolinter'] ).to be true
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'a file path is provided but is non-existent' do
|
128
|
+
let(:config_body) { "rubocop: spec/support/not/a/real/file.yml" }
|
129
|
+
it 'should puts an error message and an empty hash' do
|
130
|
+
STDOUT.should_receive(:puts).with('spec/support/not/a/real/file.yml not found')
|
131
|
+
expect( YAML.load_file(config.settings[:rubocop]) ).to eq ({})
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
44
137
|
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Maximus::GitControl do
|
4
|
+
let(:config) { {} }
|
5
|
+
let(:sha1) { 'db4aa677aa1cf8cf477d5e66df1ea875b4fa20b6' }
|
6
|
+
let(:sha2) { 'a2be59852c715382575b884e63c3e9bdee80e2db' }
|
7
|
+
|
8
|
+
subject(:git) do
|
9
|
+
conf_settings = config.merge({ root_dir: Dir.pwd })
|
10
|
+
conf = Maximus::Config.new(conf_settings)
|
11
|
+
described_class.new({ config: conf })
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '#first_commit' do
|
15
|
+
context 'a git repo exists' do
|
16
|
+
it 'should return a hash equal to the first Maximus commit' do
|
17
|
+
expect( git.first_commit ).to eq '40f2a7a7cf676a25580e04b38e3004249ed6f8ce'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#previous_commit' do
|
23
|
+
|
24
|
+
context 'a commit sha is provided' do
|
25
|
+
let(:sha) { '051ba36b4ddfcaca5361312e4f6613f6ea6ee123' }
|
26
|
+
|
27
|
+
context 'previous count is not provided' do
|
28
|
+
it 'should return the commit directly before the provided sha' do
|
29
|
+
expect( git.previous_commit(sha) ).to eq 'f0c02e5b9452fa4b8f1747aaa4fdf5c81099f575'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'previous count is provided' do
|
34
|
+
it 'should return the commit by n (previous count) commits before the provided sha' do
|
35
|
+
expect( git.previous_commit(sha, 5) ).to eq '82933a240cff983cbc0eb668cf58671fda5cc5a5'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#commit_export' do
|
44
|
+
|
45
|
+
context 'commit sha is provided' do
|
46
|
+
it 'should return a formatted hash with information' do
|
47
|
+
sha = '051ba36b4ddfcaca5361312e4f6613f6ea6ee123'
|
48
|
+
export = git.commit_export(sha)
|
49
|
+
|
50
|
+
expect( export[:commit_sha] ).to eq sha
|
51
|
+
expect( export[:message] ).to eq 'misc'
|
52
|
+
expect( export[:git_author] ).to eq 'Tim Shedor'
|
53
|
+
expect( export[:git_author_email] ).to eq 'tim@finedesigngroup.com'
|
54
|
+
expect( Time.parse export[:commit_date] ).to eq Time.parse('2014-11-11 00:19:25 -0800')
|
55
|
+
expect( export[:diff] ).to be_a(Hash)
|
56
|
+
expect( export[:remote_repo] ).to be_a(String)
|
57
|
+
expect( export[:branch] ).to be_a(String)
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'initial sha is provided' do
|
63
|
+
it 'should return a formatted hash with information' do
|
64
|
+
sha = '40f2a7a7cf676a25580e04b38e3004249ed6f8ce'
|
65
|
+
export = git.commit_export(sha)
|
66
|
+
|
67
|
+
expect( export[:commit_sha] ).to eq sha
|
68
|
+
expect( export[:message] ).to eq 'initial'
|
69
|
+
expect( export[:git_author] ).to eq 'Tim Shedor'
|
70
|
+
expect( export[:git_author_email] ).to eq 'tim@finedesigngroup.com'
|
71
|
+
expect( Time.parse export[:commit_date] ).to eq Time.parse('2014-10-31 18:16:17 -0700')
|
72
|
+
expect( export[:diff] ).to be_a(Hash)
|
73
|
+
expect( export[:remote_repo] ).to be_a(String)
|
74
|
+
expect( export[:branch] ).to be_a(String)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#associations' do
|
81
|
+
|
82
|
+
it 'should be a hash' do
|
83
|
+
expect( git.associations ).to be_a(Hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '#set_psuedo_commit' do
|
89
|
+
|
90
|
+
context 'words are provided' do
|
91
|
+
|
92
|
+
context 'master is supplied' do
|
93
|
+
let(:config) { { commit: 'master' } }
|
94
|
+
it 'should return the master sha' do
|
95
|
+
expect( git.send(:set_psuedo_commit) ).to eq `git -C #{Dir.pwd} rev-parse --branches=master HEAD`.strip!
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'last is supplied' do
|
100
|
+
let(:config) { { commit: 'last' } }
|
101
|
+
it 'should return the previous_commit sha' do
|
102
|
+
expect( git.send(:set_psuedo_commit) ).to eq `git -C #{Dir.pwd} rev-parse HEAD^`.strip!
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'working is supplied' do
|
107
|
+
let(:config) { { commit: 'working' } }
|
108
|
+
it 'should return the word "working"' do
|
109
|
+
expect( git.send(:set_psuedo_commit) ).to eq 'working'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'a commit hash is provided' do
|
116
|
+
let(:config) { { commit: '22126a6ba227d81f770d13c302e6225f7463f7be' } }
|
117
|
+
it 'should return the provided hash' do
|
118
|
+
expect( git.send(:set_psuedo_commit) ).to eq '22126a6ba227d81f770d13c302e6225f7463f7be'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#associations' do
|
125
|
+
|
126
|
+
it 'should be a hash' do
|
127
|
+
expect( git.associations ).to be_a(Hash)
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#commit_range', :isolated_environment do
|
133
|
+
|
134
|
+
context 'shas are provided' do
|
135
|
+
|
136
|
+
it 'should return an array of shas in between' do
|
137
|
+
shas = ['a2be59852c715382575b884e63c3e9bdee80e2db', 'e20fe614d323782e5cab4215942e4f22ddb98464', 'db4aa677aa1cf8cf477d5e66df1ea875b4fa20b6']
|
138
|
+
expect( git.send(:commit_range, sha1, sha2) ).to eq shas
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'duplicate shas are provided' do
|
142
|
+
let(:sha1) { 'a2be59852c715382575b884e63c3e9bdee80e2db' }
|
143
|
+
|
144
|
+
it 'should only return that commit' do
|
145
|
+
expect( git.send(:commit_range, sha1, sha2) ).to eq [sha1]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'a psuedo_commit is passed in the config' do
|
150
|
+
let(:config) { { commit: 'master' } }
|
151
|
+
it 'should not return a sha' do
|
152
|
+
expect( git.send(:commit_range, sha1, sha2) ).to eq ["git #{sha1}"]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#compare', :isolated_environment do
|
161
|
+
|
162
|
+
context 'commit is not supplied in the config' do
|
163
|
+
it 'should return a hash with commit shas, file associations, and changed line numbers' do
|
164
|
+
result = git.compare(sha1, sha2)
|
165
|
+
expect( result ).to be_a(Hash)
|
166
|
+
expect( result.keys ).to eq ["db4aa677aa1cf8cf477d5e66df1ea875b4fa20b6", "e20fe614d323782e5cab4215942e4f22ddb98464", "a2be59852c715382575b884e63c3e9bdee80e2db"]
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Maximus::Helper do
|
4
|
+
|
5
|
+
subject(:dummy_class) do
|
6
|
+
Class.new { extend Maximus::Helper }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '#is_rails?', :isolated_environment do
|
10
|
+
|
11
|
+
context 'when Rails is not defined' do
|
12
|
+
it 'should be nil' do
|
13
|
+
expect(dummy_class.is_rails?).to be_nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#root_dir', :isolated_environment do
|
20
|
+
|
21
|
+
context 'when project is not a Rails app' do
|
22
|
+
it 'should be the current directory' do
|
23
|
+
expect(dummy_class.root_dir).to eq(Dir.pwd)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#node_module_exists', :isolated_environment do
|
29
|
+
|
30
|
+
context 'when a command does not exist' do
|
31
|
+
|
32
|
+
it 'should exit the script' do
|
33
|
+
expect { dummy_class.node_module_exists('bash_func') }.to raise_error(SystemExit, "Missing command bash_func: Please run `npm install -g bash_func` And try again\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'and a custom install message is passed' do
|
37
|
+
it 'should print the install message' do
|
38
|
+
expect { dummy_class.node_module_exists('bash_func', 'premium_package_manager install') }.to raise_error(SystemExit, "Missing command bash_func: Please run `premium_package_manager install bash_func` And try again\n")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#truthy?', :isolated_environment do
|
47
|
+
|
48
|
+
context 'when a true value is passed' do
|
49
|
+
it 'should be true' do
|
50
|
+
expect( dummy_class.truthy? 'true' ).to be true
|
51
|
+
expect( dummy_class.truthy? '1' ).to be true
|
52
|
+
expect( dummy_class.truthy? 'yes' ).to be true
|
53
|
+
expect( dummy_class.truthy? 'y' ).to be true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when a false value is passed' do
|
58
|
+
it 'should be false' do
|
59
|
+
expect( dummy_class.truthy? 'false' ).to be false
|
60
|
+
expect( dummy_class.truthy? '0' ).to be false
|
61
|
+
expect( dummy_class.truthy? 'no' ).to be false
|
62
|
+
expect( dummy_class.truthy? 'n' ).to be false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#path_exists?', :isolated_environment do
|
69
|
+
|
70
|
+
context 'when a nonexistent path(s) is passed' do
|
71
|
+
it 'should be false' do
|
72
|
+
STDOUT.should_receive(:puts).with('/fake/path/to/nowhere does not exist')
|
73
|
+
expect( dummy_class.path_exists? '/fake/path/to/nowhere' ).to be false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'when a real path is passed' do
|
78
|
+
it 'should be true' do
|
79
|
+
expect( dummy_class.path_exists? '.' ).to be true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#lines_added_to_range', :isolated_environment do
|
86
|
+
|
87
|
+
context 'when a functional hash is provided' do
|
88
|
+
let(:lines_added) { { changes: ['0..5', '11..14'] } }
|
89
|
+
|
90
|
+
it 'should return an array of numbers' do
|
91
|
+
expect( dummy_class.lines_added_to_range lines_added ).to eq( [ 0,1,2,3,4,5, 11,12,13,14] )
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rainbow'
|
3
|
+
require 'rainbow/ext/string'
|
4
|
+
|
5
|
+
describe Maximus::Lint do
|
6
|
+
let(:data) {
|
7
|
+
{"/Users/Tim/dummy/app/assets/stylesheets/application.css"=>[{"line"=>1, "column"=>1, "length"=>1, "severity"=>"warning", "reason"=>"Use `//` comments everywhere", "linter"=>"Comment"}], "/Users/Tim/dummy/app/assets/stylesheets/main.css.scss"=>[{"line"=>2, "column"=>3, "length"=>16, "severity"=>"warning", "reason"=>"Properties should be ordered margin, max-width", "linter"=>"PropertySortOrder"}]}
|
8
|
+
}
|
9
|
+
|
10
|
+
subject(:lint) { described_class.new }
|
11
|
+
|
12
|
+
describe '#refine', :isolated_environment do
|
13
|
+
context 'data is blank' do
|
14
|
+
let(:data) { }
|
15
|
+
it 'should provide a blank response' do
|
16
|
+
STDOUT.should_receive(:puts).with("#{''.color(:green)}: #{'[0]'.color(:yellow)}#{' [0]'.color(:red)}")
|
17
|
+
blank_response = { lint_warnings: [], lint_errors: [], lint_conventions: [], lint_refactors: [], raw_data: "{}" }
|
18
|
+
expect( lint.refine(data) ).to eq blank_response
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'data is an error' do
|
23
|
+
let(:data) { 'No such linter available' }
|
24
|
+
it 'should report the error' do
|
25
|
+
STDOUT.should_receive(:puts).with("Error from : No such linter available")
|
26
|
+
expect( lint.refine(data) ).to be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'data is provided' do
|
31
|
+
it 'should be a Hash' do
|
32
|
+
# As a string
|
33
|
+
# Tests lint_summarize
|
34
|
+
2.times { STDOUT.should_receive(:puts).with("#{''.color(:green)}: #{'[2]'.color(:yellow)}#{' [0]'.color(:red)}") }
|
35
|
+
|
36
|
+
expect( lint.refine(data) ).to be_a(Hash)
|
37
|
+
expect( lint.refine(data.to_json) ).to be_a(Hash)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#evaluate_severities', :isolated_environment do
|
43
|
+
it 'should be a Hash' do
|
44
|
+
resp = lint.send(:evaluate_severities, data)
|
45
|
+
|
46
|
+
expect( resp ).to be_a(Hash)
|
47
|
+
expect( resp[:lint_warnings].length ).to eq 2
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|