evergreen 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +15 -0
  2. data/README.rdoc +8 -6
  3. data/lib/evergreen.rb +8 -6
  4. data/lib/evergreen/application.rb +2 -5
  5. data/lib/evergreen/helper.rb +33 -0
  6. data/lib/evergreen/runner.rb +1 -1
  7. data/lib/evergreen/server.rb +1 -0
  8. data/lib/evergreen/suite.rb +6 -0
  9. data/lib/evergreen/version.rb +1 -1
  10. data/lib/evergreen/views/run.erb +16 -6
  11. data/lib/jasmine/Contribute.markdown +8 -7
  12. data/lib/jasmine/Gemfile +0 -1
  13. data/lib/jasmine/README.markdown +1 -8
  14. data/lib/jasmine/Rakefile +26 -15
  15. data/lib/jasmine/Release.markdown +8 -6
  16. data/lib/jasmine/config.rb +29 -0
  17. data/lib/jasmine/jasmine-core.gemspec +9 -2
  18. data/lib/jasmine/jasmine_dev.thor +1 -0
  19. data/lib/jasmine/jshint/run.js +1 -1
  20. data/lib/jasmine/lib/jasmine-core/jasmine-html.js +427 -1
  21. data/lib/jasmine/lib/jasmine-core/jasmine.css +81 -166
  22. data/lib/jasmine/lib/jasmine-core/jasmine.js +245 -192
  23. data/lib/jasmine/lib/jasmine-core/version.rb +1 -1
  24. data/lib/jasmine/spec/core/MatchersSpec.js +273 -0
  25. data/lib/jasmine/spec/core/PrettyPrintSpec.js +7 -0
  26. data/lib/jasmine/spec/html/HTMLReporterSpec.js +209 -0
  27. data/lib/jasmine/spec/node_suite.js +2 -2
  28. data/lib/jasmine/spec/runner.html +10 -3
  29. data/lib/jasmine/spec/spec_helper.rb +51 -0
  30. data/lib/jasmine/spec/tasks/build_distribution_spec.rb +33 -0
  31. data/lib/jasmine/spec/tasks/build_github_pages_spec.rb +69 -0
  32. data/lib/jasmine/spec/tasks/build_standalone_distribution_spec.rb +109 -0
  33. data/lib/jasmine/spec/tasks/build_standalone_runner_spec.rb +63 -0
  34. data/lib/jasmine/spec/tasks/count_specs_spec.rb +26 -0
  35. data/lib/jasmine/spec/tasks/execute_specs_spec.rb +81 -0
  36. data/lib/jasmine/spec/tasks/jshint_spec.rb +39 -0
  37. data/lib/jasmine/spec/tasks/release_spec.rb +39 -0
  38. data/lib/jasmine/spec/tasks/version_spec.rb +55 -0
  39. data/lib/jasmine/spec/templates/runner.html.erb +3 -3
  40. data/lib/jasmine/src/core/Env.js +10 -2
  41. data/lib/jasmine/src/core/Matchers.js +33 -4
  42. data/lib/jasmine/src/core/PrettyPrinter.js +2 -2
  43. data/lib/jasmine/src/core/base.js +15 -0
  44. data/lib/jasmine/src/core/mock-timeout.js +0 -0
  45. data/lib/jasmine/src/html/HtmlReporter.js +101 -0
  46. data/lib/jasmine/src/html/HtmlReporterHelpers.js +60 -0
  47. data/lib/jasmine/src/html/ReporterView.js +164 -0
  48. data/lib/jasmine/src/html/SpecView.js +79 -0
  49. data/lib/jasmine/src/html/SuiteView.js +22 -0
  50. data/lib/jasmine/src/html/TrivialReporter.js +3 -1
  51. data/lib/jasmine/src/html/_HTMLReporter.scss +302 -0
  52. data/lib/jasmine/src/html/_TrivialReporter.scss +169 -0
  53. data/lib/jasmine/src/html/jasmine.css +81 -166
  54. data/lib/jasmine/src/html/jasmine.scss +2 -0
  55. data/lib/jasmine/src/templates/version.js.erb +1 -0
  56. data/lib/jasmine/src/version.js +3 -2
  57. data/lib/jasmine/src/version.json +1 -1
  58. data/lib/jasmine/tasks/jasmine_dev.rb +18 -0
  59. data/lib/jasmine/tasks/jasmine_dev/base.rb +54 -0
  60. data/lib/jasmine/tasks/jasmine_dev/build_distribution.rb +53 -0
  61. data/lib/jasmine/tasks/jasmine_dev/build_github_pages.rb +31 -0
  62. data/lib/jasmine/tasks/jasmine_dev/build_standalone_distribution.rb +49 -0
  63. data/lib/jasmine/tasks/jasmine_dev/build_standalone_runner.rb +59 -0
  64. data/lib/jasmine/tasks/jasmine_dev/count_specs.rb +29 -0
  65. data/lib/jasmine/tasks/jasmine_dev/execute_specs.rb +52 -0
  66. data/lib/jasmine/tasks/jasmine_dev/js_hint.rb +13 -0
  67. data/lib/jasmine/tasks/jasmine_dev/release.rb +16 -0
  68. data/lib/jasmine/tasks/jasmine_dev/sources.rb +32 -0
  69. data/lib/jasmine/tasks/jasmine_dev/version.rb +62 -0
  70. data/spec/helper_spec.rb +25 -0
  71. data/spec/suite1/spec/javascripts/{spec_helper.coffee → helpers/spec_helper.coffee} +0 -0
  72. data/spec/suite1/spec/javascripts/{spec_helper.js → helpers/spec_helper.js} +0 -0
  73. data/spec/suite1/spec/javascripts/templates_spec.js +6 -6
  74. data/spec/suite2/spec/awesome_spec.js +1 -1
  75. data/spec/suite_spec.rb +6 -0
  76. metadata +116 -52
  77. data/lib/jasmine/src/SourcesList.json +0 -7
  78. data/lib/jasmine/tasks/build_dist.rb +0 -48
  79. data/lib/jasmine/tasks/build_specs.rb +0 -50
  80. data/lib/jasmine/tasks/helpers.rb +0 -50
  81. data/lib/jasmine/tasks/pages.rb +0 -13
  82. data/lib/jasmine/tasks/spec.rb +0 -37
  83. data/lib/jasmine/tasks/standalone.rb +0 -91
  84. data/lib/jasmine/tasks/version.rb +0 -5
@@ -0,0 +1,39 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe "JSHint task" do
4
+
5
+ let(:tmp_dir) { "#{Dir.tmpdir}/jasmine_tasks_test" }
6
+ let(:jasmine_dev) { JasmineDev.new }
7
+
8
+ before do
9
+ reset_dir tmp_dir
10
+ end
11
+
12
+ describe "when Node is not present" do
13
+ before do
14
+ jasmine_dev.should_receive(:has_node?).and_return(false)
15
+ @output = capture_output { jasmine_dev.js_hint }
16
+ end
17
+
18
+ it "should not tell the user that lint is running" do
19
+ @output.should_not match(/Running JSHint/)
20
+ end
21
+
22
+ it "should prompt the user to install Node" do
23
+ @output.should match(/Node\.js is required/)
24
+ end
25
+ end
26
+
27
+ describe "when Node is present" do
28
+ before do
29
+ jasmine_dev.should_receive(:has_node?).and_return(true)
30
+
31
+ @output = capture_output { jasmine_dev.js_hint }
32
+ end
33
+
34
+ it "should tell the user that lint is running" do
35
+ @output.should match(/Running JSHint/)
36
+ @output.should match(/Jasmine JSHint PASSED/)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe "Release task" do
4
+
5
+ let(:jasmine_dev) { JasmineDev.new }
6
+
7
+ describe "when the pages submodule is not present" do
8
+ before do
9
+ jasmine_dev.should_receive(:has_pages_submodule?).and_return(false)
10
+
11
+ @output = capture_output { jasmine_dev.release_prep }
12
+ end
13
+
14
+ it "should tell the user the task is running" do
15
+ @output.should match(/Building Release/)
16
+ end
17
+
18
+ it "should prompt the user to install the submodule" do
19
+ @output.should match(/Submodule for Github Pages isn't present/)
20
+ end
21
+ end
22
+
23
+ describe "when the pages submodule is present" do
24
+ before do
25
+ JasmineDev.any_instance.should_receive(:write_version_files)
26
+ JasmineDev.any_instance.should_receive(:build_distribution)
27
+ JasmineDev.any_instance.should_receive(:build_standalone_distribution)
28
+ JasmineDev.any_instance.should_receive(:build_github_pages)
29
+
30
+ jasmine_dev.should_receive(:has_pages_submodule?).and_return(true)
31
+
32
+ @output = capture_output { jasmine_dev.release_prep }
33
+ end
34
+
35
+ it "should tell the user the task is running" do
36
+ @output.should match(/Building Release/)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe "Version tasks" do
4
+
5
+ let(:jasmine_dev) { JasmineDev.new }
6
+
7
+ describe "write_version_files" do
8
+
9
+ before do
10
+ @output = capture_output { jasmine_dev.write_version_files }
11
+ end
12
+
13
+ it "should tell the user that the task has started" do
14
+ @output.should match(/Building version files/)
15
+ end
16
+
17
+ it "should build the version.js file" do
18
+ js_version = File.read(File.join(project_root, 'src', 'version.js'))
19
+ js_version.should match(%Q{"build": #{jasmine_version_object["build"]}})
20
+ js_version.should match(%Q{"minor": #{jasmine_version_object["minor"]}})
21
+ js_version.should match(%Q{"build": #{jasmine_version_object["build"]}})
22
+
23
+ if jasmine_version_object["release_candidate"]
24
+ js_version.should match(%Q{"release_candidate": #{jasmine_version_object["release_candidate"]}})
25
+ end
26
+
27
+ js_version.should match(/"revision": \d+/)
28
+ end
29
+
30
+ it "should build the jasmine-core ruby gem version" do
31
+ ruby_version = File.read(File.join(project_root, 'lib', 'jasmine-core', 'version.rb'))
32
+ ruby_version.should match(%Q{VERSION = "#{jasmine_version}"})
33
+ end
34
+ end
35
+
36
+ describe "display_version" do
37
+ describe "when Node.js is not present" do
38
+ before do
39
+ @output = capture_output { jasmine_dev.display_version }
40
+ end
41
+
42
+ it "should display a version header" do
43
+ @output.should match(/Current version/)
44
+ end
45
+
46
+ it "should display the current version Object" do
47
+ @output.should match(/Display version: \e\[33m\d+\.\d+\.\d+/)
48
+ end
49
+
50
+ it "should display the current version string" do
51
+ @output.should match(/\{ "major": \d+, "minor": \d+, "build": \d+/)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -18,12 +18,12 @@
18
18
  var jasmineEnv = jasmine.getEnv();
19
19
  jasmineEnv.updateInterval = 1000;
20
20
 
21
- var trivialReporter = new jasmine.TrivialReporter();
21
+ var htmlReporter = new jasmine.HtmlReporter();
22
22
 
23
- jasmineEnv.addReporter(trivialReporter);
23
+ jasmineEnv.addReporter(htmlReporter);
24
24
 
25
25
  jasmineEnv.specFilter = function(spec) {
26
- return trivialReporter.specFilter(spec);
26
+ return htmlReporter.specFilter(spec);
27
27
  };
28
28
 
29
29
  var currentWindowOnload = window.onload;
@@ -230,11 +230,19 @@ jasmine.Env.prototype.equals_ = function(a, b, mismatchKeys, mismatchValues) {
230
230
  return a.getTime() == b.getTime();
231
231
  }
232
232
 
233
- if (a instanceof jasmine.Matchers.Any) {
233
+ if (a.jasmineMatches) {
234
+ return a.jasmineMatches(b);
235
+ }
236
+
237
+ if (b.jasmineMatches) {
238
+ return b.jasmineMatches(a);
239
+ }
240
+
241
+ if (a instanceof jasmine.Matchers.ObjectContaining) {
234
242
  return a.matches(b);
235
243
  }
236
244
 
237
- if (b instanceof jasmine.Matchers.Any) {
245
+ if (b instanceof jasmine.Matchers.ObjectContaining) {
238
246
  return b.matches(a);
239
247
  }
240
248
 
@@ -104,7 +104,7 @@ jasmine.Matchers.prototype.toEqual = function(expected) {
104
104
  /**
105
105
  * toNotEqual: compares the actual to the expected using the ! of jasmine.Matchers.toEqual
106
106
  * @param expected
107
- * @deprecated as of 1.0. Use not.toNotEqual() instead.
107
+ * @deprecated as of 1.0. Use not.toEqual() instead.
108
108
  */
109
109
  jasmine.Matchers.prototype.toNotEqual = function(expected) {
110
110
  return !this.env.equals_(this.actual, expected);
@@ -277,7 +277,7 @@ jasmine.Matchers.prototype.toContain = function(expected) {
277
277
  * Matcher that checks that the expected item is NOT an element in the actual Array.
278
278
  *
279
279
  * @param {Object} expected
280
- * @deprecated as of 1.0. Use not.toNotContain() instead.
280
+ * @deprecated as of 1.0. Use not.toContain() instead.
281
281
  */
282
282
  jasmine.Matchers.prototype.toNotContain = function(expected) {
283
283
  return !this.env.contains_(this.actual, expected);
@@ -345,7 +345,7 @@ jasmine.Matchers.Any = function(expectedClass) {
345
345
  this.expectedClass = expectedClass;
346
346
  };
347
347
 
348
- jasmine.Matchers.Any.prototype.matches = function(other) {
348
+ jasmine.Matchers.Any.prototype.jasmineMatches = function(other) {
349
349
  if (this.expectedClass == String) {
350
350
  return typeof other == 'string' || other instanceof String;
351
351
  }
@@ -365,7 +365,36 @@ jasmine.Matchers.Any.prototype.matches = function(other) {
365
365
  return other instanceof this.expectedClass;
366
366
  };
367
367
 
368
- jasmine.Matchers.Any.prototype.toString = function() {
368
+ jasmine.Matchers.Any.prototype.jasmineToString = function() {
369
369
  return '<jasmine.any(' + this.expectedClass + ')>';
370
370
  };
371
371
 
372
+ jasmine.Matchers.ObjectContaining = function (sample) {
373
+ this.sample = sample;
374
+ };
375
+
376
+ jasmine.Matchers.ObjectContaining.prototype.jasmineMatches = function(other, mismatchKeys, mismatchValues) {
377
+ mismatchKeys = mismatchKeys || [];
378
+ mismatchValues = mismatchValues || [];
379
+
380
+ var env = jasmine.getEnv();
381
+
382
+ var hasKey = function(obj, keyName) {
383
+ return obj != null && obj[keyName] !== jasmine.undefined;
384
+ };
385
+
386
+ for (var property in this.sample) {
387
+ if (!hasKey(other, property) && hasKey(this.sample, property)) {
388
+ mismatchKeys.push("expected has key '" + property + "', but missing from actual.");
389
+ }
390
+ else if (!env.equals_(this.sample[property], other[property], mismatchKeys, mismatchValues)) {
391
+ mismatchValues.push("'" + property + "' was '" + (other[property] ? jasmine.util.htmlEscape(other[property].toString()) : other[property]) + "' in expected, but was '" + (this.sample[property] ? jasmine.util.htmlEscape(this.sample[property].toString()) : this.sample[property]) + "' in actual.");
392
+ }
393
+ }
394
+
395
+ return (mismatchKeys.length === 0 && mismatchValues.length === 0);
396
+ };
397
+
398
+ jasmine.Matchers.ObjectContaining.prototype.jasmineToString = function () {
399
+ return "<jasmine.objectContaining(" + jasmine.pp(this.sample) + ")>";
400
+ };
@@ -23,8 +23,8 @@ jasmine.PrettyPrinter.prototype.format = function(value) {
23
23
  this.emitScalar('null');
24
24
  } else if (value === jasmine.getGlobal()) {
25
25
  this.emitScalar('<global>');
26
- } else if (value instanceof jasmine.Matchers.Any) {
27
- this.emitScalar(value.toString());
26
+ } else if (value.jasmineToString) {
27
+ this.emitScalar(value.jasmineToString());
28
28
  } else if (typeof value === 'string') {
29
29
  this.emitString(value);
30
30
  } else if (jasmine.isSpy(value)) {
@@ -196,6 +196,21 @@ jasmine.any = function(clazz) {
196
196
  return new jasmine.Matchers.Any(clazz);
197
197
  };
198
198
 
199
+ /**
200
+ * Returns a matchable subset of a JSON object. For use in expectations when you don't care about all of the
201
+ * attributes on the object.
202
+ *
203
+ * @example
204
+ * // don't care about any other attributes than foo.
205
+ * expect(mySpy).toHaveBeenCalledWith(jasmine.objectContaining({foo: "bar"});
206
+ *
207
+ * @param sample {Object} sample
208
+ * @returns matchable object for the sample
209
+ */
210
+ jasmine.objectContaining = function (sample) {
211
+ return new jasmine.Matchers.ObjectContaining(sample);
212
+ };
213
+
199
214
  /**
200
215
  * Jasmine Spies are test doubles that can act as stubs, spies, fakes or when used in an expecation, mocks.
201
216
  *
File without changes
@@ -0,0 +1,101 @@
1
+ jasmine.HtmlReporter = function(_doc) {
2
+ var self = this;
3
+ var doc = _doc || window.document;
4
+
5
+ var reporterView;
6
+
7
+ var dom = {};
8
+
9
+ // Jasmine Reporter Public Interface
10
+ self.logRunningSpecs = false;
11
+
12
+ self.reportRunnerStarting = function(runner) {
13
+ var specs = runner.specs() || [];
14
+
15
+ if (specs.length == 0) {
16
+ return;
17
+ }
18
+
19
+ createReporterDom(runner.env.versionString());
20
+ doc.body.appendChild(dom.reporter);
21
+
22
+ reporterView = new jasmine.HtmlReporter.ReporterView(dom);
23
+ reporterView.addSpecs(specs, self.specFilter);
24
+ };
25
+
26
+ self.reportRunnerResults = function(runner) {
27
+ reporterView && reporterView.complete();
28
+ };
29
+
30
+ self.reportSuiteResults = function(suite) {
31
+ reporterView.suiteComplete(suite);
32
+ };
33
+
34
+ self.reportSpecStarting = function(spec) {
35
+ if (self.logRunningSpecs) {
36
+ self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
37
+ }
38
+ };
39
+
40
+ self.reportSpecResults = function(spec) {
41
+ reporterView.specComplete(spec);
42
+ };
43
+
44
+ self.log = function() {
45
+ var console = jasmine.getGlobal().console;
46
+ if (console && console.log) {
47
+ if (console.log.apply) {
48
+ console.log.apply(console, arguments);
49
+ } else {
50
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
51
+ }
52
+ }
53
+ };
54
+
55
+ self.specFilter = function(spec) {
56
+ if (!focusedSpecName()) {
57
+ return true;
58
+ }
59
+
60
+ return spec.getFullName().indexOf(focusedSpecName()) === 0;
61
+ };
62
+
63
+ return self;
64
+
65
+ function focusedSpecName() {
66
+ var specName;
67
+
68
+ (function memoizeFocusedSpec() {
69
+ if (specName) {
70
+ return;
71
+ }
72
+
73
+ var paramMap = [];
74
+ var params = doc.location.search.substring(1).split('&');
75
+
76
+ for (var i = 0; i < params.length; i++) {
77
+ var p = params[i].split('=');
78
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
79
+ }
80
+
81
+ specName = paramMap.spec;
82
+ })();
83
+
84
+ return specName;
85
+ }
86
+
87
+ function createReporterDom(version) {
88
+ dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
89
+ dom.banner = self.createDom('div', { className: 'banner' },
90
+ self.createDom('span', { className: 'title' }, "Jasmine "),
91
+ self.createDom('span', { className: 'version' }, version)),
92
+
93
+ dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
94
+ dom.alert = self.createDom('div', {className: 'alert'}),
95
+ dom.results = self.createDom('div', {className: 'results'},
96
+ dom.summary = self.createDom('div', { className: 'summary' }),
97
+ dom.details = self.createDom('div', { id: 'details' }))
98
+ );
99
+ }
100
+ };
101
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
@@ -0,0 +1,60 @@
1
+ jasmine.HtmlReporterHelpers = {};
2
+
3
+ jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
4
+ var el = document.createElement(type);
5
+
6
+ for (var i = 2; i < arguments.length; i++) {
7
+ var child = arguments[i];
8
+
9
+ if (typeof child === 'string') {
10
+ el.appendChild(document.createTextNode(child));
11
+ } else {
12
+ if (child) {
13
+ el.appendChild(child);
14
+ }
15
+ }
16
+ }
17
+
18
+ for (var attr in attrs) {
19
+ if (attr == "className") {
20
+ el[attr] = attrs[attr];
21
+ } else {
22
+ el.setAttribute(attr, attrs[attr]);
23
+ }
24
+ }
25
+
26
+ return el;
27
+ };
28
+
29
+ jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
30
+ var results = child.results();
31
+ var status = results.passed() ? 'passed' : 'failed';
32
+ if (results.skipped) {
33
+ status = 'skipped';
34
+ }
35
+
36
+ return status;
37
+ };
38
+
39
+ jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
40
+ var parentDiv = this.dom.summary;
41
+ var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
42
+ var parent = child[parentSuite];
43
+
44
+ if (parent) {
45
+ if (typeof this.views.suites[parent.id] == 'undefined') {
46
+ this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
47
+ }
48
+ parentDiv = this.views.suites[parent.id].element;
49
+ }
50
+
51
+ parentDiv.appendChild(childElement);
52
+ };
53
+
54
+
55
+ jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
56
+ for(var fn in jasmine.HtmlReporterHelpers) {
57
+ ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
58
+ }
59
+ };
60
+
@@ -0,0 +1,164 @@
1
+ jasmine.HtmlReporter.ReporterView = function(dom) {
2
+ this.startedAt = new Date();
3
+ this.runningSpecCount = 0;
4
+ this.completeSpecCount = 0;
5
+ this.passedCount = 0;
6
+ this.failedCount = 0;
7
+ this.skippedCount = 0;
8
+
9
+ this.createResultsMenu = function() {
10
+ this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
11
+ this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
12
+ ' | ',
13
+ this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
14
+
15
+ this.summaryMenuItem.onclick = function() {
16
+ dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
17
+ };
18
+
19
+ this.detailsMenuItem.onclick = function() {
20
+ showDetails();
21
+ };
22
+ };
23
+
24
+ this.addSpecs = function(specs, specFilter) {
25
+ this.totalSpecCount = specs.length;
26
+
27
+ this.views = {
28
+ specs: {},
29
+ suites: {}
30
+ };
31
+
32
+ for (var i = 0; i < specs.length; i++) {
33
+ var spec = specs[i];
34
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
35
+ if (specFilter(spec)) {
36
+ this.runningSpecCount++;
37
+ }
38
+ }
39
+ };
40
+
41
+ this.specComplete = function(spec) {
42
+ this.completeSpecCount++;
43
+
44
+ if (isUndefined(this.views.specs[spec.id])) {
45
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
46
+ }
47
+
48
+ var specView = this.views.specs[spec.id];
49
+
50
+ switch (specView.status()) {
51
+ case 'passed':
52
+ this.passedCount++;
53
+ break;
54
+
55
+ case 'failed':
56
+ this.failedCount++;
57
+ break;
58
+
59
+ case 'skipped':
60
+ this.skippedCount++;
61
+ break;
62
+ }
63
+
64
+ specView.refresh();
65
+ this.refresh();
66
+ };
67
+
68
+ this.suiteComplete = function(suite) {
69
+ var suiteView = this.views.suites[suite.id];
70
+ if (isUndefined(suiteView)) {
71
+ return;
72
+ }
73
+ suiteView.refresh();
74
+ };
75
+
76
+ this.refresh = function() {
77
+
78
+ if (isUndefined(this.resultsMenu)) {
79
+ this.createResultsMenu();
80
+ }
81
+
82
+ // currently running UI
83
+ if (isUndefined(this.runningAlert)) {
84
+ this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
85
+ dom.alert.appendChild(this.runningAlert);
86
+ }
87
+ this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
88
+
89
+ // skipped specs UI
90
+ if (isUndefined(this.skippedAlert)) {
91
+ this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
92
+ }
93
+
94
+ this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
95
+
96
+ if (this.skippedCount === 1 && isDefined(dom.alert)) {
97
+ dom.alert.appendChild(this.skippedAlert);
98
+ }
99
+
100
+ // passing specs UI
101
+ if (isUndefined(this.passedAlert)) {
102
+ this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
103
+ }
104
+ this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
105
+
106
+ // failing specs UI
107
+ if (isUndefined(this.failedAlert)) {
108
+ this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
109
+ }
110
+ this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
111
+
112
+ if (this.failedCount === 1 && isDefined(dom.alert)) {
113
+ dom.alert.appendChild(this.failedAlert);
114
+ dom.alert.appendChild(this.resultsMenu);
115
+ }
116
+
117
+ // summary info
118
+ this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
119
+ this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
120
+ };
121
+
122
+ this.complete = function() {
123
+ dom.alert.removeChild(this.runningAlert);
124
+
125
+ this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
126
+
127
+ if (this.failedCount === 0) {
128
+ dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
129
+ } else {
130
+ showDetails();
131
+ }
132
+
133
+ dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
134
+ };
135
+
136
+ return this;
137
+
138
+ function showDetails() {
139
+ if (dom.reporter.className.search(/showDetails/) === -1) {
140
+ dom.reporter.className += " showDetails";
141
+ }
142
+ }
143
+
144
+ function isUndefined(obj) {
145
+ return typeof obj === 'undefined';
146
+ }
147
+
148
+ function isDefined(obj) {
149
+ return !isUndefined(obj);
150
+ }
151
+
152
+ function specPluralizedFor(count) {
153
+ var str = count + " spec";
154
+ if (count > 1) {
155
+ str += "s"
156
+ }
157
+ return str;
158
+ }
159
+
160
+ };
161
+
162
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
163
+
164
+