jasmine-coverage 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -59,6 +59,10 @@ it generates regardless, you can specify that in an environment variable.
59
59
 
60
60
  bundle exec rake jasmine:coverage JASMINE_COVERAGE_KEEP_TEST_RIG=true
61
61
 
62
+ You can also specify if you want missing coverage warnings
63
+
64
+ bundle exec rake jasmine:coverage JASMINE_COVERAGE_WARNINGS=true
65
+
62
66
  # How it works
63
67
 
64
68
  First Sprockets is interrogated to get a list of JS files concerned. This way, the right JS files
@@ -1,5 +1,5 @@
1
1
  module Jasmine
2
2
  module Coverage
3
- VERSION = '0.2.2'
3
+ VERSION = '0.2.4'
4
4
  end
5
5
  end
@@ -0,0 +1,2 @@
1
+ // credit to https://github.com/dankogai/js-base64
2
+ (function(global){"use strict";if(global.Base64)return;var version="2.1.1";var buffer;if(typeof module!=="undefined"&&module.exports){buffer=require("buffer").Buffer}var b64chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var b64tab=function(bin){var t={};for(var i=0,l=bin.length;i<l;i++)t[bin.charAt(i)]=i;return t}(b64chars);var fromCharCode=String.fromCharCode;var cb_utob=function(c){if(c.length<2){var cc=c.charCodeAt(0);return cc<128?c:cc<2048?fromCharCode(192|cc>>>6)+fromCharCode(128|cc&63):fromCharCode(224|cc>>>12&15)+fromCharCode(128|cc>>>6&63)+fromCharCode(128|cc&63)}else{var cc=65536+(c.charCodeAt(0)-55296)*1024+(c.charCodeAt(1)-56320);return fromCharCode(240|cc>>>18&7)+fromCharCode(128|cc>>>12&63)+fromCharCode(128|cc>>>6&63)+fromCharCode(128|cc&63)}};var re_utob=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;var utob=function(u){return u.replace(re_utob,cb_utob)};var cb_encode=function(ccc){var padlen=[0,2,1][ccc.length%3],ord=ccc.charCodeAt(0)<<16|(ccc.length>1?ccc.charCodeAt(1):0)<<8|(ccc.length>2?ccc.charCodeAt(2):0),chars=[b64chars.charAt(ord>>>18),b64chars.charAt(ord>>>12&63),padlen>=2?"=":b64chars.charAt(ord>>>6&63),padlen>=1?"=":b64chars.charAt(ord&63)];return chars.join("")};var btoa=global.btoa||function(b){return b.replace(/[\s\S]{1,3}/g,cb_encode)};var _encode=buffer?function(u){return new buffer(u).toString("base64")}:function(u){return btoa(utob(u))};var encode=function(u,urisafe){return!urisafe?_encode(u):_encode(u).replace(/[+\/]/g,function(m0){return m0=="+"?"-":"_"}).replace(/=/g,"")};var encodeURI=function(u){return encode(u,true)};var re_btou=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g");var cb_btou=function(cccc){switch(cccc.length){case 4:var cp=(7&cccc.charCodeAt(0))<<18|(63&cccc.charCodeAt(1))<<12|(63&cccc.charCodeAt(2))<<6|63&cccc.charCodeAt(3),offset=cp-65536;return fromCharCode((offset>>>10)+55296)+fromCharCode((offset&1023)+56320);case 3:return fromCharCode((15&cccc.charCodeAt(0))<<12|(63&cccc.charCodeAt(1))<<6|63&cccc.charCodeAt(2));default:return fromCharCode((31&cccc.charCodeAt(0))<<6|63&cccc.charCodeAt(1))}};var btou=function(b){return b.replace(re_btou,cb_btou)};var cb_decode=function(cccc){var len=cccc.length,padlen=len%4,n=(len>0?b64tab[cccc.charAt(0)]<<18:0)|(len>1?b64tab[cccc.charAt(1)]<<12:0)|(len>2?b64tab[cccc.charAt(2)]<<6:0)|(len>3?b64tab[cccc.charAt(3)]:0),chars=[fromCharCode(n>>>16),fromCharCode(n>>>8&255),fromCharCode(n&255)];chars.length-=[0,0,2,1][padlen];return chars.join("")};var atob=global.atob||function(a){return a.replace(/[\s\S]{1,4}/g,cb_decode)};var _decode=buffer?function(a){return new buffer(a,"base64").toString()}:function(a){return btou(atob(a))};var decode=function(a){return _decode(a.replace(/[-_]/g,function(m0){return m0=="-"?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))};global.Base64={VERSION:version,atob:atob,btoa:btoa,fromBase64:decode,toBase64:encode,utob:utob,encode:encode,encodeURI:encodeURI,btou:btou,decode:decode};if(typeof Object.defineProperty==="function"){var noEnum=function(v){return{value:v,enumerable:false,writable:true,configurable:true}};global.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",noEnum(function(){return decode(this)}));Object.defineProperty(String.prototype,"toBase64",noEnum(function(urisafe){return encode(this,urisafe)}));Object.defineProperty(String.prototype,"toBase64URI",noEnum(function(){return encode(this,true)}))}}})(this);
@@ -31,8 +31,8 @@ function generateEncodedCoverage() {
31
31
  for (var file_name in window._$jscoverage) {
32
32
  var jscov = window._$jscoverage[ file_name ];
33
33
  var file_report = rv[ file_name ] = {
34
- coverage:new Array(jscov.length),
35
- source:new Array(jscov.length)
34
+ coverage: new Array(jscov.length),
35
+ source: new Array(jscov.length)
36
36
  };
37
37
  for (var i = 0; i < jscov.length; ++i) {
38
38
  var hit_count = jscov[ i ] !== undefined ? jscov[ i ] : null;
@@ -47,7 +47,7 @@ function generateEncodedCoverage() {
47
47
 
48
48
  function coverageForAllFiles() {
49
49
 
50
- var totals = { files:0, statements:0, executed:0 };
50
+ var totals = { files: 0, statements: 0, executed: 0 };
51
51
 
52
52
  var output = "Coverage was:\n";
53
53
 
@@ -58,8 +58,14 @@ function coverageForAllFiles() {
58
58
  totals['files']++;
59
59
  totals['statements'] += simple_file_coverage['statements'];
60
60
  totals['executed'] += simple_file_coverage['executed'];
61
+ if (simple_file_coverage['missing'].length > 0 && JasmineCoverage.warnings) {
62
+ var i, ar = simple_file_coverage['missing'], l = ar.length;
63
+ for (i = 0; i < l; i++) {
64
+ console.log("\033[31m" + "WARNING -- File '" + file_name + "' has no coverage on line: " + ar[i] + "\033[0m");
65
+ }
66
+ }
61
67
 
62
- var fraction = (simple_file_coverage['executed']+"/"+simple_file_coverage['statements']).lpad(' ', 10);
68
+ var fraction = (simple_file_coverage['executed'] + "/" + simple_file_coverage['statements']).lpad(' ', 10);
63
69
  output += fraction + (" = " + simple_file_coverage['percentage'] + "").lpad(' ', 3) + "% for " + file_name + "\n";
64
70
  }
65
71
 
@@ -69,10 +75,10 @@ function coverageForAllFiles() {
69
75
  }
70
76
 
71
77
  if (totals['statements'] === 0) {
72
- log("No Javascript was found to test coverage for.");
78
+ console.log("No Javascript was found to test coverage for.");
73
79
  } else {
74
- output += ( totals['executed'] +"/"+totals['statements']+ " = "+ coverage + "").lpad(' ', 15) + "% Total\n";
75
- log(output);
80
+ output += ( totals['executed'] + "/" + totals['statements'] + " = " + coverage + "").lpad(' ', 15) + "% Total\n";
81
+ console.log(output);
76
82
  }
77
83
 
78
84
  return coverage;
@@ -120,8 +126,9 @@ function coverageForFile(fileCC) {
120
126
  var percentage = ( num_statements === 0 ? 0 : parseInt(100 * num_executed / num_statements) );
121
127
 
122
128
  return {
123
- statements:num_statements,
124
- executed:num_executed,
125
- percentage:percentage
129
+ statements: num_statements,
130
+ executed: num_executed,
131
+ percentage: percentage,
132
+ missing: missing
126
133
  };
127
134
  }
@@ -24,11 +24,11 @@ if env =~ /^(development|test)$/
24
24
  FileUtils.rm_rf output_dir
25
25
  FileUtils.mkdir_p instrumented_dir
26
26
 
27
- # The reprocessing folder map
28
- files_map = {
29
- File.expand_path('app/assets/javascripts') => instrumented_dir+'app',
30
- File.expand_path('lib/assets/javascripts') => instrumented_dir+'lib',
31
- File.expand_path('public/javascripts') => instrumented_dir+'public'
27
+ # The reprocessing folder map. Use an environment variable if available.
28
+ files_map = ENV['JS_SRC_PATH'] ? {ENV['JS_SRC_PATH'] => instrumented_dir+'public'} : {
29
+ File.expand_path('app/assets/javascripts') => instrumented_dir+'app',
30
+ File.expand_path('lib/assets/javascripts') => instrumented_dir+'lib',
31
+ File.expand_path('public/javascripts') => instrumented_dir+'public',
32
32
  }
33
33
 
34
34
  # Instrument the source files into the instrumented folders
@@ -38,6 +38,7 @@ if env =~ /^(development|test)$/
38
38
  FileUtils.mv(Dir.glob(files_map[folder]+'/jscoverage*'), output_dir)
39
39
  end
40
40
 
41
+ Jasmine::Coverage.warnings = ENV['JASMINE_COVERAGE_WARNINGS'] || 'false'
41
42
  Jasmine::Coverage.resources = files_map
42
43
  Jasmine::Coverage.output_dir = output_dir
43
44
  test_rig_folder = "#{Jasmine::Coverage.output_dir}/test-rig"
@@ -46,26 +47,40 @@ if env =~ /^(development|test)$/
46
47
 
47
48
  # Run Jasmine using the original config.
48
49
  status_code = Jasmine::Headless::Runner.run(
49
- # Any options from the options.rb file in jasmine-headless-webkit can be used here.
50
+ # Any options from the options.rb file in jasmine-headless-webkit can be used here.
50
51
 
51
- :reporters => [['File', "#{output_dir}/rawreport.txt"]]
52
+ :reporters => [['File', "#{output_dir}/rawreport.txt"]]
52
53
  )
53
- errStr = "JSCoverage exited with error code: #{status_code}.\nThis implies one of five things:\n"
54
- errStr = errStr +"0) Your JS files had exactly zero instructions. Are they all blank or just comments?\n"
55
- errStr = errStr +"1) A test failed (run bundle exec jasmine:headless to see a better error)\n"
56
- errStr = errStr +"2) The sourcecode has a syntax error (which JSLint should find)\n"
57
- errStr = errStr +"3) An error occurred in a deferred block, eg a setTimeout or underscore _.defer. This caused a window error which Jasmine will never see.\n"
58
- errStr = errStr +"4) The source files are being loaded out of sequence (so global variables are not being declared in order)\n"
59
- errStr = errStr +" To check this, run bundle exec jasmine-headless-webkit -l to see the ordering\n"
60
- errStr = errStr +"\nIn any case, try running the standard jasmine command to get better errors:\n\nbundle exec jasmine:headless\n"
61
- errStr = errStr +"\nFinally, try opening the test-rig in firefox to see the tests run in a browser and get a stacktrace. "
62
- errStr = errStr +"Chrome has strict security settings that make this difficult since it accesses the local filesystem from Javascript (but you can switch the settings off at the command line)\n\n"
63
- errStr = errStr +"\n**********************************************************************************************\n"
64
- errStr = errStr +"\nThe test rig file needs to load JS directly off disk, which Chrome prevents by default. Your best bet is to open the rig in Firefox.\n"
65
- errStr = errStr +"\nThe file can be found here: #{test_rig_folder}/jscoverage-test-rig.html\n"
66
- errStr = errStr +"\n**********************************************************************************************\n"
67
- fail errStr if status_code == 1
54
+ errStr = <<-EOS
55
+ JSCoverage exited with error code: #{status_code}
56
+
57
+ This implies one of five things:
58
+ 0) Your JS files had exactly zero instructions. Are they all blank or just comments?
59
+ 1) A test failed (run bundle exec rake jasmine:headless to see a better error)
60
+ 2) The sourcecode has a syntax error (which JSLint should find)
61
+ 3) An error occurred in a deferred block, e.g. a setTimeout or underscore _.defer. This caused a window error which Jasmine will never see.
62
+ 4) The source files are being loaded out of sequence (so global variables are not being declared in order)
63
+ To check this, run bundle exec jasmine-headless-webkit -l to see the ordering
64
+
65
+ In any case, try running the standard jasmine command to get better errors:
66
+
67
+ bundle exec rake jasmine:headless
68
+
69
+ Finally, try opening the test-rig in firefox to see the tests run in a browser and get a stacktrace. Chrome has strict security settings
70
+ that make this difficult since it accesses the local filesystem from Javascript (but you can switch the settings off at the command line).
71
+
72
+
73
+ **********************************************************************************************
74
+
75
+ The test rig file needs to load JS directly off disk, which Chrome prevents by default. Your best bet is to open the rig in Firefox.
76
+
77
+ The file can be found here: #{test_rig_folder}/jscoverage-test-rig.html
78
+
79
+ **********************************************************************************************
68
80
 
81
+ EOS
82
+
83
+ fail errStr if status_code == 1
69
84
  # Delete the test_rig folder if not required
70
85
  if ENV['JASMINE_COVERAGE_KEEP_TEST_RIG']
71
86
  p "A copy of the page and files that were used as the jasmine test environment can be found here: #{test_rig_folder}"
@@ -77,8 +92,18 @@ if env =~ /^(development|test)$/
77
92
  contents = File.open("#{output_dir}/rawreport.txt") { |f| f.read }
78
93
  # Get our Base64.
79
94
  json_report_enc = contents.split(/ENCODED-COVERAGE-EXPORT-STARTS:/m)[1]
80
- # Remove the junk at the end
81
- json_report_enc_stripped = json_report_enc[0, json_report_enc.index("\"")]
95
+ # Provide warnings to use
96
+ warning_regex = /^CONSOLE\|\|.{1,6}WARNING.{4}(.*).{5}$/
97
+ warnings = contents.scan warning_regex
98
+ if (warnings.length != 0)
99
+ puts "Detected #{warnings.length} warnings:"
100
+ puts warnings
101
+ fail "Aborting. All lines must be covered by a test." if ENV['MUST_COVER_ALL']
102
+ else
103
+ puts "No warnings detected."
104
+ end if
105
+ # Remove the junk at the end
106
+ json_report_enc_stripped = json_report_enc[0, json_report_enc.index("\"")]
82
107
 
83
108
  # Unpack it from Base64
84
109
  json_report = Base64.decode64(json_report_enc_stripped)
@@ -119,6 +144,8 @@ if env =~ /^(development|test)$/
119
144
  module Jasmine
120
145
  module Coverage
121
146
  @resources
147
+ @output_dir
148
+ @warnings
122
149
 
123
150
  def self.resources= resources
124
151
  @resources = resources
@@ -128,8 +155,6 @@ if env =~ /^(development|test)$/
128
155
  @resources
129
156
  end
130
157
 
131
- @output_dir
132
-
133
158
  def self.output_dir= output_dir
134
159
  @output_dir = output_dir
135
160
  end
@@ -137,7 +162,15 @@ if env =~ /^(development|test)$/
137
162
  def self.output_dir
138
163
  @output_dir
139
164
  end
165
+
166
+ def self.warnings= warnings
167
+ @warnings = warnings
168
+ end
169
+
170
+ def self.warnings
171
+ @warnings
172
+ end
140
173
  end
141
174
  end
142
175
 
143
- end
176
+ end
@@ -16,14 +16,11 @@ module Jasmine::Headless
16
16
  FileUtils.mkdir_p test_rigfolder
17
17
 
18
18
  p "Copying all view files and potential javascript fixture folders so the jasmine-coverage run has access to the html fixtures."
19
- FileUtils.mkdir_p "#{test_rigfolder}/target/fixtures"
20
- FileUtils.copy_entry("#{Jasmine::Coverage.output_dir}/../fixtures", "#{test_rigfolder}/target/fixtures") rescue nil
21
- FileUtils.mkdir_p "#{test_rigfolder}/target/views"
22
- FileUtils.copy_entry("#{Jasmine::Coverage.output_dir}/../views", "#{test_rigfolder}/target/views") rescue nil
23
-
24
- # Here we must also copy the spec and app folders to that we have access to all the files if we need them for the test rig
25
- FileUtils.copy_entry("#{Jasmine::Coverage.output_dir}/../../spec", "#{test_rigfolder}/spec")
26
- FileUtils.copy_entry("#{Jasmine::Coverage.output_dir}/../../app", "#{test_rigfolder}/app")
19
+ copy_assets_to_test_dir(test_rigfolder, '../fixtures', 'target/fixtures')
20
+ copy_assets_to_test_dir(test_rigfolder, '../views', 'target/views')
21
+ # Here we must also copy the spec and app folders so that we have access to all the files if we need them for the test rig
22
+ copy_assets_to_test_dir(test_rigfolder, '../../spec', 'spec')
23
+ copy_assets_to_test_dir(test_rigfolder, '../../app', 'app')
27
24
 
28
25
  jss = str.scan(/<script type="text\/javascript" src="(.*)"><\/script>/)
29
26
  jss << str.scan(/<link rel="stylesheet" href="(.*)" type="text\/css" \/>/)
@@ -52,6 +49,15 @@ module Jasmine::Headless
52
49
 
53
50
  ret
54
51
  end
52
+
53
+ private
54
+
55
+ def copy_assets_to_test_dir(test_rigfolder, from_dir, to_dir)
56
+ if File.exists? "#{Jasmine::Coverage.output_dir}/#{from_dir}"
57
+ FileUtils.mkdir_p "#{test_rigfolder}/#{to_dir}"
58
+ FileUtils.copy_entry("#{Jasmine::Coverage.output_dir}/#{from_dir}", "#{test_rigfolder}/#{to_dir}")
59
+ end
60
+ end
55
61
  end
56
62
  end
57
63
 
@@ -63,7 +69,7 @@ module Jasmine::Headless
63
69
 
64
70
  def to_html(files)
65
71
  # Declare our test runner files
66
- cov_files = ['/jscoverage.js', '/coverage_output_generator.js']
72
+ cov_files = ['/jscoverage.js', '/base64.min.js', '/coverage_output_generator.js']
67
73
 
68
74
  # Add the original files, remapping to instrumented where necessary
69
75
  tags = []
@@ -85,6 +91,8 @@ module Jasmine::Headless
85
91
  # Attach the "in context" test runners
86
92
  tags = tags + old_to_html(cov_files.map { |f| File.dirname(__FILE__)+f })
87
93
 
94
+ add_coverage_js_config(tags)
95
+
88
96
  tags
89
97
  end
90
98
 
@@ -97,5 +105,17 @@ module Jasmine::Headless
97
105
  @sprockets_environment.append_path(File.dirname(__FILE__))
98
106
  @sprockets_environment
99
107
  end
108
+
109
+ private
110
+
111
+ # This method injects the config we have defined in Ruby that needs to be present in the JS context
112
+ def add_coverage_js_config(tags)
113
+ cov_conf = "#{Jasmine::Coverage.output_dir}/coverage_config.js"
114
+ tags << "<script type=\"text/javascript\" src=\"#{cov_conf}\"></script>"
115
+
116
+ aFile = File.new(cov_conf, "w")
117
+ aFile.write("var JasmineCoverage = { warnings: #{Jasmine::Coverage.warnings}}")
118
+ aFile.close
119
+ end
100
120
  end
101
121
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jasmine-coverage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,56 +9,56 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-05 00:00:00.000000000 Z
12
+ date: 2013-05-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  type: :runtime
16
16
  name: jasmine-headless-webkit
17
17
  prerelease: false
18
18
  requirement: !ruby/object:Gem::Requirement
19
+ none: false
19
20
  requirements:
20
21
  - - ! '>='
21
22
  - !ruby/object:Gem::Version
22
23
  version: 0.9.0.rc.2
23
- none: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
25
26
  requirements:
26
27
  - - ! '>='
27
28
  - !ruby/object:Gem::Version
28
29
  version: 0.9.0.rc.2
29
- none: false
30
30
  - !ruby/object:Gem::Dependency
31
31
  type: :runtime
32
32
  name: coffee-script-source
33
33
  prerelease: false
34
34
  requirement: !ruby/object:Gem::Requirement
35
+ none: false
35
36
  requirements:
36
37
  - - ! '>='
37
38
  - !ruby/object:Gem::Version
38
39
  version: '0'
39
- none: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
41
42
  requirements:
42
43
  - - ! '>='
43
44
  - !ruby/object:Gem::Version
44
45
  version: '0'
45
- none: false
46
46
  - !ruby/object:Gem::Dependency
47
47
  type: :runtime
48
48
  name: headless
49
49
  prerelease: false
50
50
  requirement: !ruby/object:Gem::Requirement
51
+ none: false
51
52
  requirements:
52
53
  - - ! '>='
53
54
  - !ruby/object:Gem::Version
54
55
  version: '0'
55
- none: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
57
58
  requirements:
58
59
  - - ! '>='
59
60
  - !ruby/object:Gem::Version
60
61
  version: '0'
61
- none: false
62
62
  description:
63
63
  email:
64
64
  - harry@harrylascelles.com
@@ -69,6 +69,7 @@ files:
69
69
  - lib/jasmine/coverage.rb
70
70
  - lib/jasmine/coverage/version.rb
71
71
  - lib/jasmine/coverage/jasmine_coverage_railtie.rb
72
+ - lib/tasks/base64.min.js
72
73
  - lib/tasks/jasmine_headless_coverage_patches.rb
73
74
  - lib/tasks/jasmine_coverage.rake
74
75
  - lib/tasks/jscoverage.js
@@ -82,20 +83,20 @@ rdoc_options: []
82
83
  require_paths:
83
84
  - lib
84
85
  required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
85
87
  requirements:
86
88
  - - ! '>='
87
89
  - !ruby/object:Gem::Version
88
90
  version: '0'
89
- none: false
90
91
  required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
91
93
  requirements:
92
94
  - - ! '>='
93
95
  - !ruby/object:Gem::Version
94
96
  version: '0'
95
- none: false
96
97
  requirements: []
97
98
  rubyforge_project:
98
- rubygems_version: 1.8.23
99
+ rubygems_version: 1.8.25
99
100
  signing_key:
100
101
  specification_version: 3
101
102
  summary: A blend of JS unit testing and coverage