maximus 0.1.5.1 → 0.1.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,5 @@
1
1
  module Maximus
2
+ # Evaluates quality of scss
2
3
  # @since 0.1.0
3
4
  class Scsslint < Maximus::Lint
4
5
 
@@ -6,8 +7,7 @@ module Maximus
6
7
  # @see Lint#initialize
7
8
  def result
8
9
  @task = 'scsslint'
9
- @path = is_rails? ? "#{@settings[:root_dir]}/app/assets/stylesheets" : "#{@settings[:root_dir]}/source/assets/stylesheets" if @path.blank?
10
-
10
+ @path = discover_path(@config.working_dir, 'stylesheets')
11
11
  return unless temp_config(@task) && path_exists?(@path)
12
12
 
13
13
  scss = `scss-lint #{@path} -c #{temp_config(@task)} --format=JSON`
@@ -1,7 +1,6 @@
1
1
  #!/bin/bash
2
2
 
3
3
  # http://stackoverflow.com/questions/8259851/using-git-diff-how-can-i-get-added-and-modified-lines-numbers
4
- # @todo this function is tricky because I don't fully understand regex in BASH. Also, getting line hunks from git is tricky. This will likely need to be refactored
5
4
  function lines-added(){
6
5
  local path=
7
6
  local line=
@@ -64,10 +64,8 @@ module Maximus
64
64
  stats = JSON.parse(stats_cli)
65
65
  @output[:statistics][file_path.to_s] ||= {}
66
66
 
67
- # @todo is there a better way to do this?
68
67
  fp = @output[:statistics][file_path.to_s]
69
68
 
70
- # @todo Can I do like a self << thing here?
71
69
  stats.each do |stat, value|
72
70
  fp[stat.to_sym] = value
73
71
  end
@@ -1,9 +1,9 @@
1
1
  module Maximus
2
+ # Evaluate page performance
2
3
  # @since 0.1.0
3
4
  class Phantomas < Maximus::Statistic
4
5
 
5
- # Phantomas evaluates page performance with phantomjs and node
6
- #
6
+ # Run phantomas through the command line
7
7
  # @see Statistic#initialize
8
8
  def result
9
9
 
@@ -18,7 +18,7 @@ module Maximus
18
18
  # Phantomas doesn't actually skip the skip-modules defined in the config BUT here's to hoping for future support
19
19
  phantomas_cli = "phantomas --config=#{@settings[:phantomas]} "
20
20
  phantomas_cli += @config.is_dev? ? '--colors' : '--reporter=json:no-skip'
21
- phantomas_cli += " --proxy=#{@domain}"
21
+ phantomas_cli << " --proxy=#{@domain}" if @domain.include?('localhost')
22
22
  @path.is_a?(Hash) ? @path.each { |label, url| phantomas_by_url(url, phantomas_cli) } : phantomas_by_url(@path, phantomas_cli)
23
23
  @output
24
24
  end
@@ -1,8 +1,9 @@
1
1
  module Maximus
2
+ # Produce CSS statistics
2
3
  # @since 0.1.0
3
4
  class Stylestats < Maximus::Statistic
4
5
 
5
- # Produces CSS statistics
6
+ # Requires node
6
7
  # @see Statistic#initialize
7
8
  def result
8
9
 
@@ -11,7 +12,7 @@ module Maximus
11
12
  node_module_exists('stylestats')
12
13
 
13
14
  if @path.blank?
14
- @path = is_rails? ? "#{@settings[:root_dir]}/public/assets/**/*.css" : "#{@settings[:root_dir]}/**/*.css"
15
+ @path = is_rails? ? "#{@config.working_dir}/public/assets/**/*.css" : "#{@config.working_dir}/**/*.css"
15
16
  end
16
17
 
17
18
  if @path.is_a?(Array)
@@ -21,20 +22,7 @@ module Maximus
21
22
  css_files = find_css
22
23
  end
23
24
 
24
- css_files.each do |file|
25
-
26
- # For Rails, we only want the name of the compiled asset, because we know it'll live in public/assets.
27
- # If this isn't Rails, sure, give me the full path because the directory structure is likely unique
28
- pretty_name = is_rails? ? file.split('/').pop.gsub(/(-{1}[a-z0-9]{32}*\.{1}){1}/, '.') : file
29
-
30
- puts "#{'stylestats'.color(:green)}: #{pretty_name}\n\n"
31
-
32
- # include JSON formatter unless we're in dev
33
- stylestats = `stylestats #{file} --config=#{@settings[:stylestats]} #{'--type=json' unless @config.is_dev?}`
34
- refine(stylestats, pretty_name)
35
-
36
- File.delete(file)
37
- end
25
+ css_files.each { |file| stylestats_report(file) }
38
26
 
39
27
  destroy_assets if @settings[:compile_assets]
40
28
  @output
@@ -94,23 +82,22 @@ module Maximus
94
82
  # @return [Array] compiled css files
95
83
  def compile_scss_rails
96
84
  searched_files = []
97
- # @todo I'd rather Rake::Task but it's not working in different directories
98
- Dir.chdir(@settings[:root_dir]) do
99
- if @config.is_dev?
100
- # @todo review that this may not be best practice, but it's really noisy in the console
101
- quietly { `rake assets:precompile` }
102
- else
103
- `rake assets:precompile`
104
- end
85
+ # I'd rather Rake::Task but it's not working in different directories
86
+ if @config.is_dev?
87
+ # @todo review that this may not be best practice, but it's really noisy in the console
88
+ quietly { `rake -f #{@config.working_dir}/Rakefile assets:precompile` }
89
+ else
90
+ `rake -f #{@config.working_dir}/Rakefile assets:precompile`
105
91
  end
106
92
  end
107
93
 
108
94
  # Turn scss files into css files
95
+ # Skips if the file starts with an underscore
109
96
  # @see find_css_files
110
97
  # @since 0.1.5
111
98
  def compile_scss_normal
112
99
  Dir["#{@path}.scss"].select { |f| File.file? f }.each do |file|
113
- # @todo don't compile file if it starts with an underscore
100
+ next if File.basename(file).chr == '_'
114
101
  scss_file = File.open(file, 'rb') { |f| f.read }
115
102
 
116
103
  output_file = File.open( file.split('.').reverse.drop(1).reverse.join('.'), "w" )
@@ -124,14 +111,12 @@ module Maximus
124
111
  def destroy_assets
125
112
 
126
113
  if is_rails?
127
- # @todo I'd rather Rake::Task but it's not working in different directories
128
- Dir.chdir(@settings[:root_dir]) do
129
- if @config.is_dev?
130
- # @todo review that this may not be best practice, but it's really noisy in the console
131
- quietly { `rake assets:clobber` }
132
- else
133
- `rake assets:clobber`
134
- end
114
+ # I'd rather Rake::Task but it's not working in different directories
115
+ if @config.is_dev?
116
+ # @todo review that this may not be best practice, but it's really noisy in the console
117
+ quietly { `rake -f #{@config.working_dir}/Rakefile assets:clobber` }
118
+ else
119
+ `rake -f #{@config.working_dir}/Rakefile assets:clobber`
135
120
  end
136
121
  end
137
122
 
@@ -144,5 +129,24 @@ module Maximus
144
129
  Dir.glob(path).select { |f| File.file? f }.map { |file| file }
145
130
  end
146
131
 
132
+ # Present stylestat result of a CSS file
133
+ # Deletes file at end
134
+ # @since 0.1.6
135
+ # @see #result
136
+ # @param file [String] path to file
137
+ def stylestats_report(file)
138
+ # For Rails, we only want the name of the compiled asset, because we know it'll live in public/assets.
139
+ # If this isn't Rails, sure, give me the full path because the directory structure is likely unique
140
+ pretty_name = is_rails? ? file.split('/').pop.gsub(/(-{1}[a-z0-9]{32}*\.{1}){1}/, '.') : file
141
+
142
+ puts "#{'stylestats'.color(:green)}: #{pretty_name}\n\n"
143
+
144
+ # include JSON formatter unless we're in dev
145
+ stylestats = `stylestats #{file} --config=#{@settings[:stylestats]} #{'--type=json' unless @config.is_dev?}`
146
+ refine(stylestats, pretty_name)
147
+
148
+ File.delete(file)
149
+ end
150
+
147
151
  end
148
152
  end
@@ -1,9 +1,9 @@
1
1
  module Maximus
2
+ # Generates screenshots for visual regression testing
2
3
  # @since 0.1.0
3
4
  class Wraith < Maximus::Statistic
4
5
 
5
- # Generates screenshots for visual regression testing
6
- #
6
+ # Runs Wraith through command line
7
7
  # WARNING: If you call this class from a script,
8
8
  # you should delete the images generated after they've been
9
9
  # created.
@@ -30,20 +30,8 @@ module Maximus
30
30
  # in each wraith config file.
31
31
  # @yieldparam browser [String] headless browser name
32
32
  # @yieldparam configpath [String] path to temp config file (see Config#wraith_setup)
33
- @settings[:wraith].each do |browser, configpath|
34
- next unless File.file?(configpath) # prevents abortive YAML error if it can't find the file
35
- wraith_yaml = YAML.load_file(configpath)
36
- if File.directory?("#{@settings[:root_dir]}/#{wraith_yaml['history_dir']}")
37
- puts `wraith latest #{configpath}`
33
+ @settings[:wraith].each { |browser, configpath| wraith_report(browser, configpath) }
38
34
 
39
- # Reset history dir
40
- # It puts the new shots in the history folder, even with absolute paths in the config.
41
- # Could be a bug in wraith.
42
- FileUtils.remove_dir("#{@settings[:root_dir]}/#{wraith_yaml['history_dir']}")
43
- end
44
- wraith_parse browser unless @config.is_dev?
45
- puts `wraith history #{configpath}`
46
- end
47
35
  @output
48
36
 
49
37
  end
@@ -57,7 +45,7 @@ module Maximus
57
45
  # @param browser [String] headless browser used to generate the gallery
58
46
  # @return [Hash] { path: { browser, path_label, percent_changed: { size: percent_diff ] } }
59
47
  def wraith_parse(browser)
60
- Dir.glob("#{@settings[:root_dir]}/maximus_wraith_#{browser}/**/*").select { |f| File.file? f }.each do |file|
48
+ Dir.glob("#{@config.working_dir}/maximus_wraith_#{browser}/**/*").select { |f| File.file? f }.each do |file|
61
49
  extension = File.extname(file)
62
50
  next unless extension == '.png' || extension == '.txt'
63
51
 
@@ -116,5 +104,26 @@ module Maximus
116
104
  image.path
117
105
  end
118
106
 
107
+ # Generate thumbnails and history for each browser in the wraith config
108
+ # @since 0.1.6
109
+ # @see #result
110
+ # @param browser [String]
111
+ # @param configpath [String]
112
+ def wraith_report(browser, configpath)
113
+ return unless File.file?(configpath) # prevents abortive YAML error if it can't find the file
114
+ wraith_yaml = YAML.load_file(configpath)
115
+ if File.directory?(File.join(@config.working_dir, wraith_yaml['history_dir']))
116
+ puts `wraith latest #{configpath}`
117
+
118
+ # Reset history dir
119
+ # It puts the new shots in the history folder, even with absolute paths in the config.
120
+ # Could be a bug in wraith.
121
+ FileUtils.remove_dir(File.join(@config.working_dir, wraith_yaml['history_dir']))
122
+ end
123
+
124
+ wraith_parse browser unless @config.is_dev?
125
+ puts `wraith history #{configpath}`
126
+ end
127
+
119
128
  end
120
129
  end
@@ -1,3 +1,3 @@
1
1
  module Maximus
2
- VERSION = "0.1.5.1"
2
+ VERSION = "0.1.6.1"
3
3
  end
@@ -19,16 +19,17 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_runtime_dependency "git", "~> 1.2.9"
22
- spec.add_runtime_dependency "scss-lint", "~> 0.33.0"
22
+ spec.add_runtime_dependency "scss-lint", "~> 0.34.0"
23
23
  spec.add_runtime_dependency "rainbow", "2.0.0"
24
- spec.add_runtime_dependency "rubocop", "~> 0.28"
24
+ spec.add_runtime_dependency "rubocop", "~> 0.29"
25
25
  spec.add_runtime_dependency "rails_best_practices", "~> 1.15"
26
26
  spec.add_runtime_dependency "brakeman", "~> 3.0.1"
27
- spec.add_runtime_dependency "wraith", "~> 2.3"
27
+ spec.add_runtime_dependency "wraith", "~> 2.3.2"
28
28
  spec.add_runtime_dependency "activesupport"
29
29
  spec.add_runtime_dependency "thor"
30
30
 
31
31
  spec.add_development_dependency "bundler", "~> 1.6"
32
+ spec.add_development_dependency "pry-byebug", "~> 3.0"
32
33
  spec.add_development_dependency "yard", "~> 0.8"
33
34
  spec.add_development_dependency "rspec", "~> 3.0"
34
35
  spec.add_development_dependency "coveralls", "~> 0.7.8"
data/roadmap.md CHANGED
@@ -1,17 +1,12 @@
1
1
  # Roadmap
2
2
 
3
- * Check for custom lint or stat hooks in a lib/maximus folder. Add custom lint path and script execution support to maximus.yml config file
4
- * Use PhantomJS 2.0 with webfont support
5
3
  * Resolve/review @todos
6
- * Convert ruby-git to rugged (MAYBE - rugged requires libgit2)
7
- * Add SCSS specificity graph
8
- * Add HAML lint (maybe)
9
4
  * Add CSS lint (maybe)
10
5
  * Add JSLint (maybe)
11
6
  * Add W3 validator (maybe)
12
- * Add Markdown lint (maybe)
13
7
  * Add Flog support (maybe)
14
8
  * Add Flay support (maybe)
15
- * Regex path names on phantomas and wraith to defend against injection and bad characters
16
- * Test for < ruby 2.0 or require 2.0 < in gemspec
9
+ * Add PHP CodeSniffer (maybe)
10
+ * Add PHPMetrics (maybe)
11
+ * Use PHP's built-in linter (maybe)
17
12
  * If no files to inspect in working, say so
@@ -1,15 +1,78 @@
1
1
  require 'spec_helper'
2
+ require 'support/config_helper'
2
3
 
3
4
  describe Maximus::Config do
4
- let(:config_path) { '.maximus.yml' }
5
5
 
6
+ include ConfigHelper
7
+
8
+ let(:config_body) { '' }
6
9
  subject(:config) do
7
- File.write(config_path, config_body)
8
- config_contents = config_body.blank? ? {} : { config_file: config_path }
9
- described_class.new(config_contents)
10
+ create_config(config_body)
11
+ end
12
+
13
+ after(:each) { destroy_config }
14
+
15
+ describe 'options in general', :isolated_environment do
16
+ context 'options are passed directly' do
17
+ it 'should read the options as is' do
18
+ conf = described_class.new({port: 1000})
19
+
20
+ expect(conf.settings[:port]).to eq 1000
21
+ end
22
+ end
23
+
24
+ context 'options are passed through a file' do
25
+ let(:config_body) { 'port: 1000' }
26
+ it 'should parse the file accurately' do
27
+ expect(config.settings[:port]).to eq 1000
28
+ end
29
+ end
30
+
31
+ context 'options are passed through a file and directly' do
32
+ let(:config_body) { 'port: 1000' }
33
+ it 'should prefer the direct options' do
34
+ conf = described_class.new({port: 1001, config_file: '.maximus.yml'})
35
+ expect(conf.settings[:port]).to eq 1001
36
+ end
37
+ end
38
+
10
39
  end
11
40
 
12
- describe '#is_dev?', :isolated_environment do
41
+ describe 'config file loading (load_confg_file)', :isolated_environment do
42
+
43
+ context 'only maximus.yml is available' do
44
+ it 'should take the settings in maximus.yml' do
45
+ create_config('port: 1001', 'maximus.yml')
46
+ conf = described_class.new
47
+
48
+ expect(conf.settings[:port]).to eq 1001
49
+ destroy_config('maximus.yml')
50
+ end
51
+ end
52
+
53
+ context '.maximus.yml and maximus.yml are available' do
54
+ it 'should prefer .maximus.yml' do
55
+ create_config('port: 1000', '.maximus.yml')
56
+ create_config('port: 1001', 'maximus.yml')
57
+ conf = described_class.new
58
+
59
+ expect(conf.settings[:port]).to eq 1000
60
+ destroy_config('maximus.yml')
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ describe '.working_dir', :isolated_environment do
67
+ context 'root_dir is applied in the config' do
68
+ let(:config_body) { 'root_dir: some/fake/directory' }
69
+ it 'should equal the config setting' do
70
+ expect(config.working_dir).to eq 'some/fake/directory'
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '.is_dev?', :isolated_environment do
13
76
  context 'setting root value is_dev to true' do
14
77
  let(:config_body) { 'is_dev: true' }
15
78
  it 'should be true' do
@@ -18,32 +81,30 @@ describe Maximus::Config do
18
81
  end
19
82
 
20
83
  context 'is blank/not supplied' do
21
- let(:config_body) { '' }
22
84
  it 'should default to false' do
23
85
  expect(config.is_dev?).to be false
24
86
  end
25
87
  end
26
88
  end
27
89
 
28
- describe '#initialize', :isolated_environment do
90
+ describe '.initialize', :isolated_environment do
29
91
 
30
92
  context 'setting a linter to be true' do
31
93
  let(:config_body) { 'scsslint: true' }
32
94
  it 'scsslint should exist' do
33
- expect(config.settings.has_key?(:scsslint)).to be true
95
+ expect(config.settings.key?(:scsslint)).to be true
34
96
  end
35
97
  end
36
98
 
37
99
  context 'not supplying a linter but relying on the default' do
38
- let(:config_body) { '' }
39
100
  it 'should include a linter' do
40
- expect(config.settings.has_key?(:scsslint)).to be true
101
+ expect(config.settings.key?(:scsslint)).to be true
41
102
  end
42
103
  end
43
104
 
44
105
  end
45
106
 
46
- describe '#domain', :isolated_environment do
107
+ describe '.domain', :isolated_environment do
47
108
 
48
109
  context 'domain is provided' do
49
110
 
@@ -83,7 +144,7 @@ describe Maximus::Config do
83
144
 
84
145
  end
85
146
 
86
- describe '#split_paths', :isolated_environment do
147
+ describe '.split_paths', :isolated_environment do
87
148
 
88
149
  context 'an array is provided' do
89
150
  let(:config_body) { "paths: \n - '/'\n - '/about'"}
@@ -100,7 +161,6 @@ describe Maximus::Config do
100
161
  end
101
162
 
102
163
  context 'nothing is provided' do
103
- let(:config_body) { '' }
104
164
  it 'should return the default path with label' do
105
165
  expect( config.settings[:paths] ).to eq ({ 'home' => '/'})
106
166
  end
@@ -111,10 +171,29 @@ describe Maximus::Config do
111
171
  describe '#load_config', :isolated_environment do
112
172
 
113
173
  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
174
+
175
+ context 'at a local address' do
176
+ let(:config_body) { 'rubocop: spec/support/rubocop.yml' }
177
+ it 'should load the file' do
178
+ expect( YAML.load_file(config.settings[:rubocop])['Rubolinter'] ).to be true
179
+ end
180
+ end
181
+
182
+ context 'at an available remote address' do
183
+ let(:config_body) { 'rubocop: "https://raw.githubusercontent.com/wearefine/standards/master/linters/.rubocop.yml" ' }
184
+ it 'should load the file' do
185
+ expect( YAML.load_file(config.settings[:rubocop]) ).to be_a(Hash)
186
+ end
117
187
  end
188
+
189
+ context 'at an unavailable remote address' do
190
+ let(:config_body) { 'rubocop: "http://raw.githubusercontent.com/wearefine/standards/master/linters/nonexistent_file.yml" ' }
191
+ it 'should report an error and return an empty hash' do
192
+ STDOUT.should_receive(:puts).with('http://raw.githubusercontent.com/wearefine/standards/master/linters/nonexistent_file.yml not accessible')
193
+ expect( YAML.load_file(config.settings[:rubocop]) ).to eq({})
194
+ end
195
+ end
196
+
118
197
  end
119
198
 
120
199
  context 'settings are provided' do