maximus 0.1.4 → 0.1.5
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 +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
|