newjs 1.7.2 → 1.7.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.
Files changed (49) hide show
  1. data/Manifest.txt +13 -2
  2. data/Rakefile +11 -20
  3. data/app_generators/newjs/templates/test/assets/jsunittest.js +173 -135
  4. data/app_generators/newjs_iphone/templates/Html/test/assets/jsunittest.js +173 -135
  5. data/app_generators/newjs_screwunit/USAGE +5 -0
  6. data/app_generators/newjs_screwunit/newjs_screwunit_generator.rb +61 -0
  7. data/app_generators/newjs_screwunit/templates/Rakefile.erb +34 -0
  8. data/bin/newjs_screwunit +17 -0
  9. data/features/development.feature +5 -5
  10. data/features/imported_files_for_generators.feature +2 -2
  11. data/features/newjs_screwunit.feature +18 -0
  12. data/features/step_definitions/cli_steps.rb +9 -0
  13. data/features/{steps/common.rb → step_definitions/common_steps.rb} +39 -81
  14. data/features/step_definitions/file_comparison_steps.rb +10 -0
  15. data/features/support/common.rb +29 -0
  16. data/features/support/env.rb +15 -0
  17. data/features/support/matchers.rb +11 -0
  18. data/lib/newjs.rb +1 -1
  19. data/rack_generators/javascript_test/templates/assets/jsunittest.js +173 -135
  20. data/rails_generators/javascript_test/templates/assets/jsunittest.js +173 -135
  21. data/test/test_newjs_screwunit_generator.rb +43 -0
  22. data/vendor/jsunittest/History.txt +9 -0
  23. data/vendor/jsunittest/Rakefile +1 -1
  24. data/vendor/jsunittest/dist/jsunittest-0.7.3.js +1042 -0
  25. data/vendor/jsunittest/dist/jsunittest.js +173 -135
  26. data/vendor/jsunittest/src/ajax.js +2 -1
  27. data/vendor/jsunittest/src/assertions.js +49 -78
  28. data/vendor/jsunittest/src/common.js +83 -24
  29. data/vendor/jsunittest/src/jsunittest.js +7 -998
  30. data/vendor/jsunittest/src/logger.js +6 -6
  31. data/vendor/jsunittest/src/message_template.js +1 -1
  32. data/vendor/jsunittest/src/prototype/event.js +2 -2
  33. data/vendor/jsunittest/src/prototype/template.js +7 -6
  34. data/vendor/jsunittest/src/runner.js +13 -12
  35. data/vendor/jsunittest/src/test_case.js +11 -6
  36. data/vendor/jsunittest/test/unit/assertions_test.html +9 -1
  37. data/vendor/jsunittest/test/unit/common_test.html +9 -1
  38. data/vendor/jsunittest/test/unit/logger_test.html +2 -2
  39. data/vendor/jsunittest/test/unit/message_template_test.html +2 -2
  40. data/vendor/jsunittest/test/unit/runner_test.html +2 -2
  41. data/vendor/jsunittest/test/unit/template_test.html +2 -2
  42. data/vendor/jsunittest/test/unit/test_case_test.html +24 -3
  43. data/vendor/jsunittest/website/images/logo_bundle.png +0 -0
  44. data/vendor/jsunittest/website/index.html +3 -3
  45. data/vendor/jsunittest/website/index.txt +1 -1
  46. data/vendor/jsunittest/website/stylesheets/screen.css +3 -0
  47. data/vendor/jsunittest/website/tmbundle/JavaScript Unit Testing.tmbundle.tar.gz +0 -0
  48. metadata +20 -14
  49. data/features/steps/env.rb +0 -6
@@ -37,14 +37,23 @@ app_generators/newjs_iphone/templates/Html/src/library.js.erb
37
37
  app_generators/newjs_iphone/templates/Html/tasks/javascript_test_autotest_tasks.rake
38
38
  app_generators/newjs_iphone/templates/Html/test/assets/jsunittest.js
39
39
  app_generators/newjs_iphone/templates/Html/test/assets/unittest.css
40
+ app_generators/newjs_screwunit/USAGE
41
+ app_generators/newjs_screwunit/newjs_screwunit_generator.rb
42
+ app_generators/newjs_screwunit/templates/Rakefile.erb
40
43
  bin/newjs
41
44
  bin/newjs_iphone
45
+ bin/newjs_screwunit
42
46
  config/website.yml
43
47
  config/website.yml.sample
44
48
  features/development.feature
45
49
  features/imported_files_for_generators.feature
46
- features/steps/common.rb
47
- features/steps/env.rb
50
+ features/newjs_screwunit.feature
51
+ features/step_definitions/cli_steps.rb
52
+ features/step_definitions/common_steps.rb
53
+ features/step_definitions/file_comparison_steps.rb
54
+ features/support/common.rb
55
+ features/support/env.rb
56
+ features/support/matchers.rb
48
57
  javascript_test_generators/functional_test/USAGE
49
58
  javascript_test_generators/functional_test/functional_test_generator.rb
50
59
  javascript_test_generators/functional_test/templates/test/assets/jshoulda.js
@@ -125,6 +134,7 @@ test/test_helper.rb
125
134
  test/test_install_website_generator.rb
126
135
  test/test_newjs_generator.rb
127
136
  test/test_newjs_iphone_generator.rb
137
+ test/test_newjs_screwunit_generator.rb
128
138
  test/test_page_generator.rb
129
139
  test/test_plain_theme_generator.rb
130
140
  test/test_rack_javascript_test.rb
@@ -206,6 +216,7 @@ vendor/jsunittest/Rakefile
206
216
  vendor/jsunittest/config/deploy.rb
207
217
  vendor/jsunittest/config/website.yml.sample
208
218
  vendor/jsunittest/dist/jsunittest-0.7.2.js
219
+ vendor/jsunittest/dist/jsunittest-0.7.3.js
209
220
  vendor/jsunittest/dist/jsunittest.js
210
221
  vendor/jsunittest/dist/unittest.css
211
222
  vendor/jsunittest/lib/jstest.rb
data/Rakefile CHANGED
@@ -1,26 +1,17 @@
1
- %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
- require File.dirname(__FILE__) + '/lib/newjs'
1
+ gem 'hoe', '>= 2.3'
2
+ require 'hoe'
3
+ require './lib/newjs'
3
4
 
4
- # Generate all the Rake tasks
5
- # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
- $hoe = Hoe.new('newjs', Newjs::VERSION) do |p|
7
- p.developer('Dr Nic Williams', 'drnicwilliams@gmail.com')
8
- p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
- # p.extra_deps = [
10
- # ['activesupport','>= 2.0.2'],
11
- # ]
12
- p.extra_dev_deps = [
13
- ['newgem', ">= #{::Newgem::VERSION}"]
14
- ]
15
-
16
- p.clean_globs |= %w[**/.DS_Store tmp *.log]
17
- path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
18
- p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
19
- p.rsync_args = '-av --delete --ignore-errors'
5
+ Hoe.plugin :newgem
6
+ Hoe.plugin :website
7
+ Hoe.plugin :cucumberfeatures
8
+
9
+ Hoe.spec('newjs') do
10
+ developer 'Dr Nic Williams', 'drnicwilliams@gmail.com'
11
+ extra_dev_deps << ['newgem', ">= #{::Newgem::VERSION}"]
12
+ $hoe = self
20
13
  end
21
14
 
22
- require 'newgem/tasks' # load /tasks/*.rake
23
15
  Dir['tasks/**/*.rake'].each { |t| load t }
24
16
 
25
- # TODO - want other tests/tasks run by default? Add them to the list
26
17
  task :default => [:features]
@@ -1,4 +1,4 @@
1
- /* Jsunittest, version 0.7.2
1
+ /* Jsunittest, version 0.7.3
2
2
  * (c) 2008 Dr Nic Williams
3
3
  *
4
4
  * Jsunittest is freely distributable under
@@ -11,34 +11,57 @@ var JsUnitTest = {
11
11
  Unit: {},
12
12
  inspect: function(object) {
13
13
  try {
14
- if (typeof object == "undefined") return 'undefined';
15
- if (object === null) return 'null';
14
+ if (typeof object == "undefined") {return 'undefined';}
15
+ if (object === null) {return 'null';}
16
16
  if (typeof object == "string") {
17
17
  var useDoubleQuotes = arguments[1];
18
18
  var escapedString = this.gsub(object, /[\x00-\x1f\\]/, function(match) {
19
- var character = String.specialChar[match[0]];
20
- return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
19
+ var character = {
20
+ '\b': '\\b',
21
+ '\t': '\\t',
22
+ '\n': '\\n',
23
+ '\f': '\\f',
24
+ '\r': '\\r',
25
+ '\\': '\\\\'
26
+ }[match[0]];
27
+ return character ? character : '\\u00' + JsUnitTest.toHexString(match[0].charCodeAt());
21
28
  });
22
- if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
29
+ if (useDoubleQuotes) {return '"' + escapedString.replace(/"/g, '\\"') + '"';}
23
30
  return "'" + escapedString.replace(/'/g, '\\\'') + "'";
24
- };
31
+ }
32
+ if (JsUnitTest.getClass(object) === 'Object') {
33
+ var keys_values = new Array(), prefix = 'Object: { ';
34
+ for (property in object) {
35
+ keys_values.push(property + ': ' + object[property]);
36
+ }
37
+ return (prefix + keys_values.join(', ') + ' }');
38
+ }
25
39
  return String(object);
26
40
  } catch (e) {
27
- if (e instanceof RangeError) return '...';
41
+ if (e instanceof RangeError) {return '...';}
28
42
  throw e;
29
43
  }
30
44
  },
31
- $: function(element) {
45
+
46
+ getClass: function(object) {
47
+ return Object.prototype.toString.call(object)
48
+ .match(/^\[object\s(.*)\]$/)[1];
49
+ },
50
+
51
+ $: function(element) {
32
52
  if (arguments.length > 1) {
33
- for (var i = 0, elements = [], length = arguments.length; i < length; i++)
53
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++) {
34
54
  elements.push(this.$(arguments[i]));
55
+ }
35
56
  return elements;
36
57
  }
37
- if (typeof element == "string")
58
+ if (typeof element == "string") {
38
59
  element = document.getElementById(element);
60
+ }
39
61
  return element;
40
62
  },
41
- gsub: function(source, pattern, replacement) {
63
+
64
+ gsub: function(source, pattern, replacement) {
42
65
  var result = '', match;
43
66
  replacement = arguments.callee.prepareReplacement(replacement);
44
67
 
@@ -60,15 +83,48 @@ var JsUnitTest = {
60
83
  escapeHTML: function(data) {
61
84
  return data.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
62
85
  },
86
+ toHexString : function(n) {
87
+ var string = n.toString(16);
88
+ return '00'.substring(string.length) + string;
89
+ },
63
90
  arrayfromargs: function(args) {
64
91
  var myarray = new Array();
65
92
  var i;
66
93
 
67
- for (i=0;i<args.length;i++)
68
- myarray[i] = args[i];
94
+ for (i=0;i<args.length;i++) {
95
+ myarray[i] = args[i];
96
+ }
69
97
 
70
98
  return myarray;
71
99
  },
100
+
101
+ // from now we recursively zip & compare nested arrays
102
+ areArraysEqual: function(expected, actual) {
103
+ var expected_array = JsUnitTest.flattenArray(expected);
104
+ var actual_array = JsUnitTest.flattenArray(actual);
105
+ if (expected_array.length == actual_array.length) {
106
+ for (var i=0; i < expected_array.length; i++) {
107
+ if (expected_array[i] != actual_array[i]) {return false;}
108
+ }
109
+ return true;
110
+ }
111
+ return false;
112
+ },
113
+
114
+ areArraysNotEqual: function(expected, actual) {
115
+ return !this.areArraysEqual(expected, actual);
116
+ },
117
+
118
+ areHashesEqual: function(expected, actual) {
119
+ var expected_array = JsUnitTest.hashToSortedArray(expected);
120
+ var actual_array = JsUnitTest.hashToSortedArray(actual);
121
+ return this.areArraysEqual(expected_array, actual_array);
122
+ },
123
+
124
+ areHashesNotEqual: function(expected, actual) {
125
+ return !this.areHashesEqual(expected, actual);
126
+ },
127
+
72
128
  hashToSortedArray: function(hash) {
73
129
  var results = [];
74
130
  for (key in hash) {
@@ -86,7 +142,7 @@ var JsUnitTest = {
86
142
  } else {
87
143
  results.push(object);
88
144
  }
89
- };
145
+ }
90
146
  return results;
91
147
  },
92
148
  selectorMatch: function(expression, element) {
@@ -151,7 +207,7 @@ var JsUnitTest = {
151
207
 
152
208
  var match = true, name, matches;
153
209
  for (var i = 0, token; token = tokens[i]; i++) {
154
- name = token[0], matches = token[1];
210
+ name = token[0]; matches = token[1];
155
211
  if (!assertions[name](element, matches)) {
156
212
  match = false; break;
157
213
  }
@@ -159,10 +215,11 @@ var JsUnitTest = {
159
215
 
160
216
  return match;
161
217
  },
218
+
162
219
  toQueryParams: function(query, separator) {
163
220
  var query = query || window.location.search;
164
221
  var match = query.replace(/^\s+/, '').replace(/\s+$/, '').match(/([^?#]*)(#.*)?$/);
165
- if (!match) return { };
222
+ if (!match) {return { };}
166
223
 
167
224
  var hash = {};
168
225
  var parts = match[1].split(separator || '&');
@@ -171,18 +228,20 @@ var JsUnitTest = {
171
228
  if (pair[0]) {
172
229
  var key = decodeURIComponent(pair.shift());
173
230
  var value = pair.length > 1 ? pair.join('=') : pair[0];
174
- if (value != undefined) value = decodeURIComponent(value);
231
+ if (value != undefined) {value = decodeURIComponent(value);}
175
232
 
176
233
  if (key in hash) {
177
234
  var object = hash[key];
178
235
  var isArray = object != null && typeof object == "object" &&
179
- 'splice' in object && 'join' in object
180
- if (!isArray) hash[key] = [hash[key]];
236
+ 'splice' in object && 'join' in object;
237
+ if (!isArray) {hash[key] = [hash[key]];}
181
238
  hash[key].push(value);
182
239
  }
183
- else hash[key] = value;
240
+ else {
241
+ hash[key] = value;
242
+ }
184
243
  }
185
- };
244
+ }
186
245
  return hash;
187
246
  },
188
247
 
@@ -194,12 +253,12 @@ var JsUnitTest = {
194
253
  };
195
254
 
196
255
  JsUnitTest.gsub.prepareReplacement = function(replacement) {
197
- if (typeof replacement == "function") return replacement;
256
+ if (typeof replacement == "function") {return replacement;}
198
257
  var template = new Template(replacement);
199
- return function(match) { return template.evaluate(match) };
258
+ return function(match) { return template.evaluate(match); };
200
259
  };
201
260
 
202
- JsUnitTest.Version = '0.7.2';
261
+ JsUnitTest.Version = '0.7.3';
203
262
 
204
263
  JsUnitTest.Template = function(template, pattern) {
205
264
  this.template = template; //template.toString();
@@ -207,31 +266,32 @@ JsUnitTest.Template = function(template, pattern) {
207
266
  };
208
267
 
209
268
  JsUnitTest.Template.prototype.evaluate = function(object) {
210
- if (typeof object.toTemplateReplacements == "function")
269
+ if (typeof object.toTemplateReplacements == "function") {
211
270
  object = object.toTemplateReplacements();
271
+ }
212
272
 
213
273
  return JsUnitTest.gsub(this.template, this.pattern, function(match) {
214
- if (object == null) return '';
274
+ if (object == null) {return '';}
215
275
 
216
276
  var before = match[1] || '';
217
- if (before == '\\') return match[2];
277
+ if (before == '\\') {return match[2];}
218
278
 
219
279
  var ctx = object, expr = match[3];
220
280
  var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
221
281
  match = pattern.exec(expr);
222
- if (match == null) return before;
282
+ if (match == null) {return before;}
223
283
 
224
284
  while (match != null) {
225
285
  var comp = (match[1].indexOf('[]') === 0) ? match[2].gsub('\\\\]', ']') : match[1];
226
286
  ctx = ctx[comp];
227
- if (null == ctx || '' == match[3]) break;
287
+ if (null == ctx || '' == match[3]) {break;}
228
288
  expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
229
289
  match = pattern.exec(expr);
230
290
  }
231
291
 
232
292
  return before + JsUnitTest.String.interpret(ctx);
233
293
  });
234
- }
294
+ };
235
295
 
236
296
  JsUnitTest.Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
237
297
  JsUnitTest.Event = {};
@@ -246,9 +306,9 @@ JsUnitTest.Event.addEvent = function(element, type, handler) {
246
306
  element.addEventListener(type, handler, false);
247
307
  } else {
248
308
  // assign each event handler a unique ID
249
- if (!handler.$$guid) handler.$$guid = JsUnitTest.Event.addEvent.guid++;
309
+ if (!handler.$$guid) {handler.$$guid = JsUnitTest.Event.addEvent.guid++;}
250
310
  // create a hash table of event types for the element
251
- if (!element.events) element.events = {};
311
+ if (!element.events) {element.events = {};}
252
312
  // create a hash table of event handlers for each element/event pair
253
313
  var handlers = element.events[type];
254
314
  if (!handlers) {
@@ -309,11 +369,11 @@ JsUnitTest.Event.fixEvent.stopPropagation = function() {
309
369
 
310
370
  JsUnitTest.Unit.Logger = function(element) {
311
371
  this.element = JsUnitTest.$(element);
312
- if (this.element) this._createLogTable();
372
+ if (this.element) {this._createLogTable();}
313
373
  };
314
374
 
315
375
  JsUnitTest.Unit.Logger.prototype.start = function(testName) {
316
- if (!this.element) return;
376
+ if (!this.element) {return;}
317
377
  var tbody = this.element.getElementsByTagName('tbody')[0];
318
378
 
319
379
  var tr = document.createElement('tr');
@@ -322,7 +382,7 @@ JsUnitTest.Unit.Logger.prototype.start = function(testName) {
322
382
  //testname
323
383
  td = document.createElement('td');
324
384
  td.appendChild(document.createTextNode(testName));
325
- tr.appendChild(td)
385
+ tr.appendChild(td);
326
386
 
327
387
  tr.appendChild(document.createElement('td'));//status
328
388
  tr.appendChild(document.createElement('td'));//message
@@ -338,13 +398,13 @@ JsUnitTest.Unit.Logger.prototype.setStatus = function(status) {
338
398
  };
339
399
 
340
400
  JsUnitTest.Unit.Logger.prototype.finish = function(status, summary) {
341
- if (!this.element) return;
401
+ if (!this.element) {return;}
342
402
  this.setStatus(status);
343
403
  this.message(summary);
344
404
  };
345
405
 
346
406
  JsUnitTest.Unit.Logger.prototype.message = function(message) {
347
- if (!this.element) return;
407
+ if (!this.element) {return;}
348
408
  var cell = this.getMessageCell();
349
409
 
350
410
  // cell.appendChild(document.createTextNode(this._toHTML(message)));
@@ -352,7 +412,7 @@ JsUnitTest.Unit.Logger.prototype.message = function(message) {
352
412
  };
353
413
 
354
414
  JsUnitTest.Unit.Logger.prototype.summary = function(summary) {
355
- if (!this.element) return;
415
+ if (!this.element) {return;}
356
416
  var div = this.element.getElementsByTagName('div')[0];
357
417
  div.innerHTML = this._toHTML(summary);
358
418
  };
@@ -406,7 +466,7 @@ JsUnitTest.Unit.MessageTemplate.prototype.evaluate = function(params) {
406
466
  var part = this.parts[i];
407
467
  var result = (part == '?') ? JsUnitTest.inspect(params.shift()) : part.replace(/\\\?/, '?');
408
468
  results.push(result);
409
- };
469
+ }
410
470
  return results.join('');
411
471
  };
412
472
  // A generic function for performming AJAX requests
@@ -522,8 +582,9 @@ JsUnitTest.ajax = function( options ) {
522
582
 
523
583
  // If the specified type is "script", execute the returned text
524
584
  // response as if it was JavaScript
525
- if ( type == "script" )
585
+ if ( type == "script" ) {
526
586
  eval.call( window, data );
587
+ }
527
588
 
528
589
  // Return the response data (either an XML Document or a text string)
529
590
  return data;
@@ -538,170 +599,140 @@ JsUnitTest.Unit.Assertions = {
538
599
  },
539
600
 
540
601
  flunk: function(message) {
541
- this.assertBlock(message || 'Flunked', function() { return false });
602
+ this.assertBlock(message || 'Flunked', function() { return false; });
542
603
  },
543
604
 
544
605
  assertBlock: function(message, block) {
545
606
  try {
546
607
  block.call(this) ? this.pass() : this.fail(message);
547
- } catch(e) { this.error(e) }
608
+ } catch(e) { this.error(e); }
548
609
  },
549
610
 
550
611
  assert: function(expression, message) {
551
612
  message = this.buildMessage(message || 'assert', 'got <?>', expression);
552
- this.assertBlock(message, function() { return expression });
613
+ this.assertBlock(message, function() { return expression; });
553
614
  },
554
615
 
555
616
  assertEqual: function(expected, actual, message) {
556
617
  message = this.buildMessage(message || 'assertEqual', 'expected <?>, actual: <?>', expected, actual);
557
- this.assertBlock(message, function() { return expected == actual });
618
+ this.assertBlock(message, function() { return expected == actual; });
558
619
  },
559
620
 
560
621
  assertNotEqual: function(expected, actual, message) {
561
622
  message = this.buildMessage(message || 'assertNotEqual', 'expected <?>, actual: <?>', expected, actual);
562
- this.assertBlock(message, function() { return expected != actual });
623
+ this.assertBlock(message, function() { return expected != actual; });
563
624
  },
564
625
 
565
626
  assertEnumEqual: function(expected, actual, message) {
566
627
  message = this.buildMessage(message || 'assertEnumEqual', 'expected <?>, actual: <?>', expected, actual);
567
- var expected_array = JsUnitTest.flattenArray(expected);
568
- var actual_array = JsUnitTest.flattenArray(actual);
569
- this.assertBlock(message, function() {
570
- if (expected_array.length == actual_array.length) {
571
- for (var i=0; i < expected_array.length; i++) {
572
- if (expected_array[i] != actual_array[i]) return false;
573
- };
574
- return true;
575
- }
576
- return false;
577
- });
628
+ this.assertBlock(message, function() { return JsUnitTest.areArraysEqual(expected, actual); });
578
629
  },
579
630
 
580
631
  assertEnumNotEqual: function(expected, actual, message) {
581
632
  message = this.buildMessage(message || 'assertEnumNotEqual', '<?> was the same as <?>', expected, actual);
582
- var expected_array = JsUnitTest.flattenArray(expected);
583
- var actual_array = JsUnitTest.flattenArray(actual);
584
- this.assertBlock(message, function() {
585
- if (expected_array.length == actual_array.length) {
586
- for (var i=0; i < expected_array.length; i++) {
587
- if (expected_array[i] != actual_array[i]) return true;
588
- };
589
- return false;
590
- }
591
- return true;
592
- });
633
+ this.assertBlock(message, function() { return JsUnitTest.areArraysNotEqual(expected, actual); });
593
634
  },
594
635
 
595
636
  assertHashEqual: function(expected, actual, message) {
596
- message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', expected, actual);
597
- var expected_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(expected));
598
- var actual_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(actual));
599
- var block = function() {
600
- if (expected_array.length == actual_array.length) {
601
- for (var i=0; i < expected_array.length; i++) {
602
- if (expected_array[i] != actual_array[i]) return false;
603
- };
604
- return true;
605
- }
606
- return false;
607
- };
608
- this.assertBlock(message, block);
637
+ message = this.buildMessage(message || 'assertHashEqual', 'expected <?>, actual: <?>', JsUnitTest.inspect(expected), JsUnitTest.inspect(actual));
638
+ this.assertBlock(message, function() { return JsUnitTest.areHashesEqual(expected, actual); });
609
639
  },
610
640
 
611
641
  assertHashNotEqual: function(expected, actual, message) {
612
- message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', expected, actual);
613
- var expected_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(expected));
614
- var actual_array = JsUnitTest.flattenArray(JsUnitTest.hashToSortedArray(actual));
615
- // from now we recursively zip & compare nested arrays
616
- var block = function() {
617
- if (expected_array.length == actual_array.length) {
618
- for (var i=0; i < expected_array.length; i++) {
619
- if (expected_array[i] != actual_array[i]) return true;
620
- };
621
- return false;
622
- }
623
- return true;
624
- };
625
- this.assertBlock(message, block);
642
+ message = this.buildMessage(message || 'assertHashNotEqual', '<?> was the same as <?>', JsUnitTest.inspect(expected), JsUnitTest.inspect(actual));
643
+ this.assertBlock(message, function() { return JsUnitTest.areHashesNotEqual(expected, actual); });
626
644
  },
627
645
 
628
646
  assertIdentical: function(expected, actual, message) {
629
647
  message = this.buildMessage(message || 'assertIdentical', 'expected <?>, actual: <?>', expected, actual);
630
- this.assertBlock(message, function() { return expected === actual });
648
+ this.assertBlock(message, function() { return expected === actual; });
631
649
  },
632
650
 
633
651
  assertNotIdentical: function(expected, actual, message) {
634
652
  message = this.buildMessage(message || 'assertNotIdentical', 'expected <?>, actual: <?>', expected, actual);
635
- this.assertBlock(message, function() { return expected !== actual });
653
+ this.assertBlock(message, function() { return expected !== actual; });
636
654
  },
637
655
 
638
656
  assertNull: function(obj, message) {
639
657
  message = this.buildMessage(message || 'assertNull', 'got <?>', obj);
640
- this.assertBlock(message, function() { return obj === null });
658
+ this.assertBlock(message, function() { return obj === null; });
641
659
  },
642
660
 
643
661
  assertNotNull: function(obj, message) {
644
662
  message = this.buildMessage(message || 'assertNotNull', 'got <?>', obj);
645
- this.assertBlock(message, function() { return obj !== null });
663
+ this.assertBlock(message, function() { return obj !== null; });
646
664
  },
647
665
 
648
666
  assertUndefined: function(obj, message) {
649
667
  message = this.buildMessage(message || 'assertUndefined', 'got <?>', obj);
650
- this.assertBlock(message, function() { return typeof obj == "undefined" });
668
+ this.assertBlock(message, function() { return typeof obj == "undefined"; });
651
669
  },
652
670
 
653
671
  assertNotUndefined: function(obj, message) {
654
672
  message = this.buildMessage(message || 'assertNotUndefined', 'got <?>', obj);
655
- this.assertBlock(message, function() { return typeof obj != "undefined" });
673
+ this.assertBlock(message, function() { return typeof obj != "undefined"; });
656
674
  },
657
675
 
658
676
  assertNullOrUndefined: function(obj, message) {
659
677
  message = this.buildMessage(message || 'assertNullOrUndefined', 'got <?>', obj);
660
- this.assertBlock(message, function() { return obj == null });
678
+ this.assertBlock(message, function() { return obj == null; });
661
679
  },
662
680
 
663
681
  assertNotNullOrUndefined: function(obj, message) {
664
682
  message = this.buildMessage(message || 'assertNotNullOrUndefined', 'got <?>', obj);
665
- this.assertBlock(message, function() { return obj != null });
683
+ this.assertBlock(message, function() { return obj != null; });
666
684
  },
667
685
 
668
686
  assertMatch: function(expected, actual, message) {
669
687
  message = this.buildMessage(message || 'assertMatch', 'regex <?> did not match <?>', expected, actual);
670
- this.assertBlock(message, function() { return new RegExp(expected).exec(actual) });
688
+ this.assertBlock(message, function() { return new RegExp(expected).exec(actual); });
671
689
  },
672
690
 
673
691
  assertNoMatch: function(expected, actual, message) {
674
692
  message = this.buildMessage(message || 'assertNoMatch', 'regex <?> matched <?>', expected, actual);
675
- this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)) });
693
+ this.assertBlock(message, function() { return !(new RegExp(expected).exec(actual)); });
676
694
  },
677
695
 
678
696
  assertHasClass: function(element, klass, message) {
679
697
  element = JsUnitTest.$(element);
680
698
  message = this.buildMessage(message || 'assertHasClass', '? doesn\'t have class <?>.', element, klass);
681
699
  this.assertBlock(message, function() {
682
- return !!element.className.match(new RegExp(klass))
700
+ var elementClassName = element.className;
701
+ return (elementClassName.length > 0 && (elementClassName == klass ||
702
+ new RegExp("(^|\\s)" + klass + "(\\s|$)").test(elementClassName)));
703
+ // return !!element.className.match(new RegExp(klass))
704
+ });
705
+ },
706
+
707
+ assertNotHasClass: function(element, klass, message) {
708
+ element = JsUnitTest.$(element);
709
+ message = this.buildMessage(message || 'assertNotHasClass', '? does have class <?>.', element, klass);
710
+ this.assertBlock(message, function() {
711
+ var elementClassName = element.className;
712
+ return !(elementClassName.length > 0 && (elementClassName == klass ||
713
+ new RegExp("(^|\\s)" + klass + "(\\s|$)").test(elementClassName)));
683
714
  });
684
715
  },
685
716
 
686
717
  assertHidden: function(element, message) {
687
718
  element = JsUnitTest.$(element);
688
719
  message = this.buildMessage(message || 'assertHidden', '? isn\'t hidden.', element);
689
- this.assertBlock(message, function() { return !element.style.display || element.style.display == 'none' });
720
+ this.assertBlock(message, function() { return !element.style.display || element.style.display == 'none'; });
690
721
  },
691
722
 
692
723
  assertInstanceOf: function(expected, actual, message) {
693
724
  message = this.buildMessage(message || 'assertInstanceOf', '<?> was not an instance of the expected type', actual);
694
- this.assertBlock(message, function() { return actual instanceof expected });
725
+ this.assertBlock(message, function() { return actual instanceof expected; });
695
726
  },
696
727
 
697
728
  assertNotInstanceOf: function(expected, actual, message) {
698
729
  message = this.buildMessage(message || 'assertNotInstanceOf', '<?> was an instance of the expected type', actual);
699
- this.assertBlock(message, function() { return !(actual instanceof expected) });
730
+ this.assertBlock(message, function() { return !(actual instanceof expected); });
700
731
  },
701
732
 
702
733
  assertRespondsTo: function(method, obj, message) {
703
734
  message = this.buildMessage(message || 'assertRespondsTo', 'object doesn\'t respond to <?>', method);
704
- this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function') });
735
+ this.assertBlock(message, function() { return (method in obj && typeof obj[method] == 'function'); });
705
736
  },
706
737
 
707
738
  assertRaise: function(exceptionName, method, message) {
@@ -711,8 +742,8 @@ JsUnitTest.Unit.Assertions = {
711
742
  method();
712
743
  return false;
713
744
  } catch(e) {
714
- if (e.name == exceptionName) return true;
715
- else throw e;
745
+ if (e.name == exceptionName) {return true;}
746
+ else {throw e;}
716
747
  }
717
748
  };
718
749
  this.assertBlock(message, block);
@@ -730,22 +761,23 @@ JsUnitTest.Unit.Assertions = {
730
761
 
731
762
  _isVisible: function(element) {
732
763
  element = JsUnitTest.$(element);
733
- if(!element.parentNode) return true;
764
+ if(!element.parentNode) {return true;}
734
765
  this.assertNotNull(element);
735
- if(element.style && (element.style.display == 'none'))
766
+ if(element.style && (element.style.display == 'none')) {
736
767
  return false;
768
+ }
737
769
 
738
770
  return arguments.callee.call(this, element.parentNode);
739
771
  },
740
772
 
741
773
  assertVisible: function(element, message) {
742
774
  message = this.buildMessage(message, '? was not visible.', element);
743
- this.assertBlock(message, function() { return this._isVisible(element) });
775
+ this.assertBlock(message, function() { return this._isVisible(element); });
744
776
  },
745
777
 
746
778
  assertNotVisible: function(element, message) {
747
779
  message = this.buildMessage(message, '? was not hidden and didn\'t have a hidden parent either.', element);
748
- this.assertBlock(message, function() { return !this._isVisible(element) });
780
+ this.assertBlock(message, function() { return !this._isVisible(element); });
749
781
  },
750
782
 
751
783
  assertElementsMatch: function() {
@@ -766,7 +798,7 @@ JsUnitTest.Unit.Assertions = {
766
798
  message = this.buildMessage('assertElementsMatch', 'In index <?>: expected <?> but got ?', index, expression, element);
767
799
  this.flunk(message);
768
800
  pass = false;
769
- };
801
+ }
770
802
  this.assert(pass, "Expected all elements to match.");
771
803
  },
772
804
 
@@ -799,7 +831,7 @@ JsUnitTest.Unit.Runner.prototype.portNumber = function() {
799
831
  if (window.location.search.length > 0) {
800
832
  var matches = window.location.search.match(/\:(\d{3,5})\//);
801
833
  if (matches) {
802
- return parseInt(matches[1]);
834
+ return parseInt(matches[1], 10);
803
835
  }
804
836
  }
805
837
  return null;
@@ -807,22 +839,23 @@ JsUnitTest.Unit.Runner.prototype.portNumber = function() {
807
839
 
808
840
  JsUnitTest.Unit.Runner.prototype.getTests = function(testcases) {
809
841
  var tests = [], options = this.options;
810
- if (this.queryParams.tests) tests = this.queryParams.tests.split(',');
811
- else if (options.tests) tests = options.tests;
812
- else if (options.test) tests = [option.test];
842
+ if (this.queryParams.tests) {tests = this.queryParams.tests.split(',');}
843
+ else if (options.tests) {tests = options.tests;}
844
+ else if (options.test) {tests = [option.test];}
813
845
  else {
814
846
  for (testname in testcases) {
815
- if (testname.match(/^test/)) tests.push(testname);
847
+ if (testname.match(/^test/)) {tests.push(testname);}
816
848
  }
817
849
  }
818
850
  var results = [];
819
851
  for (var i=0; i < tests.length; i++) {
820
852
  var test = tests[i];
821
- if (testcases[test])
853
+ if (testcases[test]) {
822
854
  results.push(
823
855
  new JsUnitTest.Unit.Testcase(test, testcases[test], testcases.setup, testcases.teardown)
824
856
  );
825
- };
857
+ }
858
+ }
826
859
  return results;
827
860
  };
828
861
 
@@ -841,7 +874,7 @@ JsUnitTest.Unit.Runner.prototype.getResult = function() {
841
874
  results.failures += test.failures;
842
875
  results.errors += test.errors;
843
876
  results.warnings += test.warnings;
844
- };
877
+ }
845
878
  return results;
846
879
  };
847
880
 
@@ -859,15 +892,15 @@ JsUnitTest.Unit.Runner.prototype.postResults = function() {
859
892
  JsUnitTest.ajax({
860
893
  url: url,
861
894
  type: 'GET'
862
- })
895
+ });
863
896
  }
864
897
  };
865
898
 
866
899
  JsUnitTest.Unit.Runner.prototype.runTests = function() {
867
900
  var test = this.tests[this.currentTest], actions;
868
901
 
869
- if (!test) return this.finish();
870
- if (!test.isWaiting) this.logger.start(test.name);
902
+ if (!test) {return this.finish();}
903
+ if (!test.isWaiting) {this.logger.start(test.name);}
871
904
  test.run();
872
905
  var self = this;
873
906
  if(test.isWaiting) {
@@ -880,7 +913,7 @@ JsUnitTest.Unit.Runner.prototype.runTests = function() {
880
913
  }
881
914
 
882
915
  this.logger.finish(test.status(), test.summary());
883
- if (actions = test.actions) this.logger.appendActionButtons(actions);
916
+ if (actions = test.actions) {this.logger.appendActionButtons(actions);}
884
917
  this.currentTest++;
885
918
  // tail recursive, hopefully the browser will skip the stackframe
886
919
  this.runTests();
@@ -927,7 +960,7 @@ JsUnitTest.Unit.Testcase.prototype.wait = function(time, nextPart) {
927
960
  JsUnitTest.Unit.Testcase.prototype.run = function(rethrow) {
928
961
  try {
929
962
  try {
930
- if (!this.isWaiting) this.setup();
963
+ if (!this.isWaiting) {this.setup();}
931
964
  this.isWaiting = false;
932
965
  this.test();
933
966
  } finally {
@@ -937,7 +970,7 @@ JsUnitTest.Unit.Testcase.prototype.run = function(rethrow) {
937
970
  }
938
971
  }
939
972
  catch(e) {
940
- if (rethrow) throw e;
973
+ if (rethrow) {throw e;}
941
974
  this.error(e, this);
942
975
  }
943
976
  };
@@ -981,14 +1014,19 @@ JsUnitTest.Unit.Testcase.prototype.info = function(message) {
981
1014
 
982
1015
  JsUnitTest.Unit.Testcase.prototype.error = function(error, test) {
983
1016
  this.errors++;
984
- this.actions['retry with throw'] = function() { test.run(true) };
1017
+ this.actions['retry with throw'] = function() { test.run(true); };
985
1018
  this.messages.push(error.name + ": "+ error.message + "(" + JsUnitTest.inspect(error) + ")");
1019
+ if( typeof console != "undefined" && console.error) {
1020
+ console.error("Test '" + test.name + "' died, exception and test follows");
1021
+ console.error(error);
1022
+ console.error(test.test.toString());
1023
+ }
986
1024
  };
987
1025
 
988
1026
  JsUnitTest.Unit.Testcase.prototype.status = function() {
989
- if (this.failures > 0) return 'failed';
990
- if (this.errors > 0) return 'error';
991
- if (this.warnings > 0) return 'warning';
1027
+ if (this.failures > 0) {return 'failed';}
1028
+ if (this.errors > 0) {return 'error';}
1029
+ if (this.warnings > 0) {return 'warning';}
992
1030
  return 'passed';
993
1031
  };
994
1032