jasmine-coverage 0.2.2 → 0.2.4

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.
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