learn-test 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +23 -0
  6. data/README.md +38 -0
  7. data/Rakefile +2 -0
  8. data/bin/learn-test +78 -0
  9. data/learn-test.gemspec +30 -0
  10. data/lib/learn_test.rb +26 -0
  11. data/lib/learn_test/file_finder.rb +12 -0
  12. data/lib/learn_test/github_interactor.rb +23 -0
  13. data/lib/learn_test/jasmine/boot.js +184 -0
  14. data/lib/learn_test/jasmine/console.js +161 -0
  15. data/lib/learn_test/jasmine/formatters/jasmine2-junit.js +199 -0
  16. data/lib/learn_test/jasmine/helpers/ConsoleHelper.js +12 -0
  17. data/lib/learn_test/jasmine/helpers/ConsoleHelperNoColor.js +12 -0
  18. data/lib/learn_test/jasmine/initializer.rb +27 -0
  19. data/lib/learn_test/jasmine/jasmine-html.js +360 -0
  20. data/lib/learn_test/jasmine/jasmine-jquery.js +813 -0
  21. data/lib/learn_test/jasmine/jasmine.css +56 -0
  22. data/lib/learn_test/jasmine/jasmine.js +2403 -0
  23. data/lib/learn_test/jasmine/jasmine_favicon.png +0 -0
  24. data/lib/learn_test/jasmine/jquery-1.8.0.min.js +2 -0
  25. data/lib/learn_test/jasmine/jquery-ui-1.8.23.custom.min.js +125 -0
  26. data/lib/learn_test/jasmine/phantom_checker.rb +55 -0
  27. data/lib/learn_test/jasmine/runner.rb +129 -0
  28. data/lib/learn_test/jasmine/runners/SpecRunner.html +35 -0
  29. data/lib/learn_test/jasmine/runners/run-jasmine.js +228 -0
  30. data/lib/learn_test/jasmine/templates/SpecRunnerTemplate.html.erb +35 -0
  31. data/lib/learn_test/jasmine/templates/SpecRunnerTemplateNoColor.html.erb +35 -0
  32. data/lib/learn_test/jasmine/templates/requires.yml.example +7 -0
  33. data/lib/learn_test/jasmine/vendor/require.js +2077 -0
  34. data/lib/learn_test/netrc_interactor.rb +18 -0
  35. data/lib/learn_test/python_unittest/nose_installer.rb +35 -0
  36. data/lib/learn_test/python_unittest/requirements_checker.rb +57 -0
  37. data/lib/learn_test/python_unittest/runner.rb +89 -0
  38. data/lib/learn_test/repo_parser.rb +22 -0
  39. data/lib/learn_test/rspec/runner.rb +113 -0
  40. data/lib/learn_test/spec_type_parser.rb +26 -0
  41. data/lib/learn_test/user_id_parser.rb +9 -0
  42. data/lib/learn_test/username_parser.rb +19 -0
  43. data/lib/learn_test/version.rb +3 -0
  44. data/spec/features/jasmine_jquery_fixtures_spec.rb +10 -0
  45. data/spec/features/rspec_unit_spec.rb +10 -0
  46. data/spec/fixtures/jasmine-jquery-fixtures/index.html +10 -0
  47. data/spec/fixtures/jasmine-jquery-fixtures/requires.yml +4 -0
  48. data/spec/fixtures/jasmine-jquery-fixtures/spec/jasmine-jquery-fixtures-spec.js +11 -0
  49. data/spec/fixtures/rspec-unit-spec/.rspec +2 -0
  50. data/spec/fixtures/rspec-unit-spec/lib/dog.rb +2 -0
  51. data/spec/fixtures/rspec-unit-spec/spec/dog_spec.rb +7 -0
  52. data/spec/fixtures/rspec-unit-spec/spec/spec_helper.rb +93 -0
  53. data/spec/repo_parser_spec.rb +25 -0
  54. data/spec/spec_helper.rb +10 -0
  55. metadata +237 -0
@@ -0,0 +1,161 @@
1
+ /*
2
+ Copyright (c) 2008-2013 Pivotal Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+ function getJasmineRequireObj() {
24
+ if (typeof module !== "undefined" && module.exports) {
25
+ return exports;
26
+ } else {
27
+ window.jasmineRequire = window.jasmineRequire || {};
28
+ return window.jasmineRequire;
29
+ }
30
+ }
31
+
32
+ getJasmineRequireObj().console = function(jRequire, j$) {
33
+ j$.ConsoleReporter = jRequire.ConsoleReporter();
34
+ };
35
+
36
+ getJasmineRequireObj().ConsoleReporter = function() {
37
+
38
+ var noopTimer = {
39
+ start: function(){},
40
+ elapsed: function(){ return 0; }
41
+ };
42
+
43
+ function ConsoleReporter(options) {
44
+ var print = options.print,
45
+ showColors = options.showColors || false,
46
+ onComplete = options.onComplete || function() {},
47
+ timer = options.timer || noopTimer,
48
+ specCount,
49
+ failureCount,
50
+ failedSpecs = [],
51
+ pendingCount,
52
+ ansi = {
53
+ green: '\x1B[32m',
54
+ red: '\x1B[31m',
55
+ yellow: '\x1B[33m',
56
+ none: '\x1B[0m'
57
+ };
58
+
59
+ this.jasmineStarted = function() {
60
+ specCount = 0;
61
+ failureCount = 0;
62
+ pendingCount = 0;
63
+ print("Started");
64
+ printNewline();
65
+ timer.start();
66
+ };
67
+
68
+ this.jasmineDone = function() {
69
+ printNewline();
70
+ for (var i = 0; i < failedSpecs.length; i++) {
71
+ specFailureDetails(failedSpecs[i]);
72
+ }
73
+
74
+ printNewline();
75
+ var specCounts = specCount + " " + plural("spec", specCount) + ", " +
76
+ failureCount + " " + plural("failure", failureCount);
77
+
78
+ if (pendingCount) {
79
+ specCounts += ", " + pendingCount + " pending " + plural("spec", pendingCount);
80
+ }
81
+
82
+ print(specCounts);
83
+
84
+ printNewline();
85
+ var seconds = timer.elapsed() / 1000;
86
+ print("Finished in " + seconds + " " + plural("second", seconds));
87
+
88
+ printNewline();
89
+
90
+ onComplete(failureCount === 0);
91
+ };
92
+
93
+ this.specDone = function(result) {
94
+ specCount++;
95
+
96
+ if (result.status == "pending") {
97
+ pendingCount++;
98
+ print(colored("yellow", "*"));
99
+ return;
100
+ }
101
+
102
+ if (result.status == "passed") {
103
+ print(colored("green", '.'));
104
+ return;
105
+ }
106
+
107
+ if (result.status == "failed") {
108
+ failureCount++;
109
+ failedSpecs.push(result);
110
+ print(colored("red", 'F'));
111
+ }
112
+ };
113
+
114
+ return this;
115
+
116
+ function printNewline() {
117
+ print("\n");
118
+ }
119
+
120
+ function colored(color, str) {
121
+ return showColors ? (ansi[color] + str + ansi.none) : str;
122
+ }
123
+
124
+ function plural(str, count) {
125
+ return count == 1 ? str : str + "s";
126
+ }
127
+
128
+ function repeat(thing, times) {
129
+ var arr = [];
130
+ for (var i = 0; i < times; i++) {
131
+ arr.push(thing);
132
+ }
133
+ return arr;
134
+ }
135
+
136
+ function indent(str, spaces) {
137
+ var lines = (str || '').split("\n");
138
+ var newArr = [];
139
+ for (var i = 0; i < lines.length; i++) {
140
+ newArr.push(repeat(" ", spaces).join("") + lines[i]);
141
+ }
142
+ return newArr.join("\n");
143
+ }
144
+
145
+ function specFailureDetails(result) {
146
+ printNewline();
147
+ print(result.fullName);
148
+
149
+ for (var i = 0; i < result.failedExpectations.length; i++) {
150
+ var failedExpectation = result.failedExpectations[i];
151
+ printNewline();
152
+ print(indent(failedExpectation.stack, 2));
153
+ }
154
+
155
+ printNewline();
156
+ }
157
+ }
158
+
159
+ return ConsoleReporter;
160
+ };
161
+
@@ -0,0 +1,199 @@
1
+ (function() {
2
+ "use strict";
3
+
4
+ function getJasmineRequireObj() {
5
+ if (typeof module !== "undefined" && module.exports) {
6
+ return exports;
7
+ } else {
8
+ window.jasmineRequire = window.jasmineRequire || {};
9
+ return window.jasmineRequire;
10
+ }
11
+ }
12
+
13
+ if (typeof getJasmineRequireObj() == 'undefined') {
14
+ throw new Error("jasmine 2.0 must be loaded before jasmine-junit");
15
+ }
16
+
17
+ getJasmineRequireObj().JUnitXmlReporter = function() {
18
+
19
+
20
+ function JUnitXmlReporter(options) {
21
+ var runStartTime;
22
+ var specStartTime;
23
+ var suiteLevel = -1;
24
+ var suites = []
25
+ var currentSuite;
26
+ var totalNumberOfSpecs;
27
+ var totalNumberOfFailures;
28
+
29
+ this.jasmineStarted = function(started) {
30
+ totalNumberOfSpecs = started.totalSpecsDefined;
31
+ runStartTime = new Date();
32
+ };
33
+
34
+ this.jasmineDone = function() {
35
+ // console.log('Jasmine ran in ', elapsed(runStartTime, new Date()), ' seconds')
36
+ window.done = true
37
+ };
38
+
39
+ this.suiteStarted = function(result) {
40
+ suiteLevel++;
41
+ if (suiteLevel == 0) {
42
+ totalNumberOfSpecs = 0;
43
+ totalNumberOfFailures = 0;
44
+ suites.push(result);
45
+ currentSuite = result;
46
+ currentSuite.startTime = new Date();
47
+ currentSuite.noOfSpecs = 0;
48
+ currentSuite.noOfFails = 0;
49
+ currentSuite.specs = [];
50
+ }
51
+ };
52
+
53
+ this.suiteDone = function(result) {
54
+ if (suiteLevel == 0) {
55
+ currentSuite.endTime = new Date();
56
+ writeFile('.', descToFilename(result.description), suiteToJUnitXml(currentSuite))
57
+ }
58
+ suiteLevel--;
59
+ };
60
+
61
+ this.specStarted = function(result) {
62
+ specStartTime = new Date();
63
+ };
64
+
65
+ this.specDone = function(result) {
66
+ totalNumberOfSpecs++;
67
+
68
+ if (isFailed(result)) {
69
+ currentSuite.noOfFails++;
70
+ }
71
+ result.startTime = specStartTime;
72
+ result.endTime = new Date();
73
+ currentSuite.specs.push(result);
74
+ currentSuite.noOfSpecs++;
75
+ };
76
+
77
+ return this;
78
+
79
+ }
80
+
81
+ return JUnitXmlReporter;
82
+ };
83
+
84
+ function isFailed(result) {
85
+ return result.status === 'failed'
86
+ }
87
+
88
+ function isSkipped(result) {
89
+ return result.status === 'pending'
90
+ }
91
+
92
+ function suiteToJUnitXml(suite) {
93
+ var resultXml = '<?xml version="1.0" encoding="UTF-8"?>\n';
94
+ resultXml += '<testsuites>\n';
95
+ resultXml += '\t<testsuite tests="' + suite.noOfSpecs + '" errors="0" failures="' + suite.noOfFails + '" time="' + elapsed(suite.startTime, suite.endTime) + '" timestamp="' + ISODateString(suite.startTime) + '">\n'
96
+ for (var i = 0; i < suite.specs.length; i++) {
97
+ resultXml += specToJUnitXml(suite.specs[i], suite.description);
98
+ }
99
+ resultXml += '\t</testsuite>\n</testsuites>\n\n'
100
+ return resultXml;
101
+ }
102
+
103
+ function specToJUnitXml(spec, suiteId) {
104
+ var xml = '\t\t<testcase classname="' + suiteId +
105
+ '" name="' + escapeInvalidXmlChars(spec.fullName.replace(suiteId+" ", "")) + '" time="' + elapsed(spec.startTime, spec.endTime) + '">\n';
106
+ if (isSkipped(spec)) {
107
+ xml += '\t\t\t<skipped />\n';
108
+ }
109
+ if (isFailed(spec)) {
110
+ xml += failedToJUnitXml(spec.failedExpectations)
111
+ }
112
+ xml += '\t\t</testcase>\n'
113
+ return xml;
114
+ }
115
+
116
+ function failedToJUnitXml(failedExpectations) {
117
+ var failure;
118
+ var failureXml = ""
119
+ for (var i = 0; i < failedExpectations.length; i++) {
120
+ failure = failedExpectations[i];
121
+ failureXml += '\t\t\t<failure type="' + failure.matcherName + '" message="' + trim(escapeInvalidXmlChars(failure.message)) + '">\n';
122
+ failureXml += escapeInvalidXmlChars(failure.stack || failure.message);
123
+ failureXml += "\t\t\t</failure>\n";
124
+ }
125
+
126
+ return failureXml;
127
+ }
128
+
129
+ function descToFilename(desc) {
130
+ return 'TEST-' + desc + '.xml';
131
+ }
132
+
133
+ function ISODateString(d) {
134
+ function pad(n) {
135
+ return n < 10 ? '0' + n : n;
136
+ }
137
+
138
+ return d.getFullYear() + '-' +
139
+ pad(d.getMonth() + 1) + '-' +
140
+ pad(d.getDate()) + 'T' +
141
+ pad(d.getHours()) + ':' +
142
+ pad(d.getMinutes()) + ':' +
143
+ pad(d.getSeconds());
144
+ }
145
+
146
+ function elapsed(startTime, endTime) {
147
+ return (endTime - startTime) / 1000;
148
+ }
149
+
150
+ function trim(str) {
151
+ return str.replace(/^\s+/, "").replace(/\s+$/, "");
152
+ }
153
+
154
+ function escapeInvalidXmlChars(str) {
155
+ return str.replace(/</g, "&lt;")
156
+ .replace(/\>/g, "&gt;")
157
+ .replace(/\"/g, "&quot;")
158
+ .replace(/\'/g, "&apos;")
159
+ .replace(/\&/g, "&amp;");
160
+ }
161
+
162
+ function writeFile(path, filename, text) {
163
+ function getQualifiedFilename(separator) {
164
+ if (path && path.substr(-1) !== separator && filename.substr(0) !== separator) {
165
+ path += separator;
166
+ }
167
+ return path + filename;
168
+ }
169
+
170
+ // PhantomJS
171
+ if(typeof(__phantom_writeFile) !== 'undefined') {
172
+ try {
173
+ // turn filename into a qualified path
174
+ filename = getQualifiedFilename(window.fs_path_separator);
175
+ // function injected by jasmine-runner.js
176
+ __phantom_writeFile(filename, text);
177
+ return;
178
+ } catch (error) {
179
+ console.log('Error writing file', error)
180
+ }
181
+ }
182
+
183
+ // Node.js
184
+ if(typeof(global) !== 'undefined') {
185
+ try {
186
+ var fs = require("fs");
187
+ var nodejs_path = require("path");
188
+ var fd = fs.openSync(nodejs_path.join(path, filename), "w");
189
+ fs.writeSync(fd, text, 0);
190
+ fs.closeSync(fd);
191
+ return;
192
+ } catch (error) {
193
+ console.log('Error writing file', error)
194
+ }
195
+ }
196
+ }
197
+
198
+ })()
199
+
@@ -0,0 +1,12 @@
1
+ if (navigator.userAgent.indexOf("PhantomJS") > 0) {
2
+ var consoleReporter = new jasmineRequire.ConsoleReporter()({
3
+ showColors: true,
4
+ timer: new jasmine.Timer,
5
+ print: function() {
6
+ console.log.apply(console, arguments)
7
+ }
8
+ });
9
+
10
+ jasmine.getEnv().addReporter(consoleReporter);
11
+ }
12
+
@@ -0,0 +1,12 @@
1
+ if (navigator.userAgent.indexOf("PhantomJS") > 0) {
2
+ var consoleReporter = new jasmineRequire.ConsoleReporter()({
3
+ showColors: false,
4
+ timer: new jasmine.Timer,
5
+ print: function() {
6
+ console.log.apply(console, arguments)
7
+ }
8
+ });
9
+
10
+ jasmine.getEnv().addReporter(consoleReporter);
11
+ }
12
+
@@ -0,0 +1,27 @@
1
+ module LearnTest
2
+ module Jasmine
3
+ class Initializer
4
+ def self.run
5
+ new.run
6
+ end
7
+
8
+ def run
9
+ make_spec_directory
10
+ generate_app_js
11
+ end
12
+
13
+ def make_spec_directory
14
+ FileUtils.mkdir_p('spec')
15
+ FileUtils.touch('spec/.keep')
16
+ end
17
+
18
+ def generate_app_js
19
+ FileUtils.cp(
20
+ "#{FileFinder.location_to_dir('templates')}/requires.yml.example",
21
+ 'requires.yml'
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,360 @@
1
+ /*
2
+ Copyright (c) 2008-2013 Pivotal Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ */
23
+ jasmineRequire.html = function(j$) {
24
+ j$.ResultsNode = jasmineRequire.ResultsNode();
25
+ j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
26
+ j$.QueryString = jasmineRequire.QueryString();
27
+ j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
28
+ };
29
+
30
+ jasmineRequire.HtmlReporter = function(j$) {
31
+
32
+ var noopTimer = {
33
+ start: function() {},
34
+ elapsed: function() { return 0; }
35
+ };
36
+
37
+ function HtmlReporter(options) {
38
+ var env = options.env || {},
39
+ getContainer = options.getContainer,
40
+ createElement = options.createElement,
41
+ createTextNode = options.createTextNode,
42
+ onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
43
+ timer = options.timer || noopTimer,
44
+ results = [],
45
+ specsExecuted = 0,
46
+ failureCount = 0,
47
+ pendingSpecCount = 0,
48
+ htmlReporterMain,
49
+ symbols;
50
+
51
+ this.initialize = function() {
52
+ htmlReporterMain = createDom("div", {className: "html-reporter"},
53
+ createDom("div", {className: "banner"},
54
+ createDom("span", {className: "title"}, "Jasmine"),
55
+ createDom("span", {className: "version"}, j$.version)
56
+ ),
57
+ createDom("ul", {className: "symbol-summary"}),
58
+ createDom("div", {className: "alert"}),
59
+ createDom("div", {className: "results"},
60
+ createDom("div", {className: "failures"})
61
+ )
62
+ );
63
+ getContainer().appendChild(htmlReporterMain);
64
+
65
+ symbols = find(".symbol-summary");
66
+ };
67
+
68
+ var totalSpecsDefined;
69
+ this.jasmineStarted = function(options) {
70
+ totalSpecsDefined = options.totalSpecsDefined || 0;
71
+ timer.start();
72
+ };
73
+
74
+ var summary = createDom("div", {className: "summary"});
75
+
76
+ var topResults = new j$.ResultsNode({}, "", null),
77
+ currentParent = topResults;
78
+
79
+ this.suiteStarted = function(result) {
80
+ currentParent.addChild(result, "suite");
81
+ currentParent = currentParent.last();
82
+ };
83
+
84
+ this.suiteDone = function(result) {
85
+ if (currentParent == topResults) {
86
+ return;
87
+ }
88
+
89
+ currentParent = currentParent.parent;
90
+ };
91
+
92
+ this.specStarted = function(result) {
93
+ currentParent.addChild(result, "spec");
94
+ };
95
+
96
+ var failures = [];
97
+ this.specDone = function(result) {
98
+ if (result.status != "disabled") {
99
+ specsExecuted++;
100
+ }
101
+
102
+ symbols.appendChild(createDom("li", {
103
+ className: result.status,
104
+ id: "spec_" + result.id,
105
+ title: result.fullName
106
+ }
107
+ ));
108
+
109
+ if (result.status == "failed") {
110
+ failureCount++;
111
+
112
+ var failure =
113
+ createDom("div", {className: "spec-detail failed"},
114
+ createDom("div", {className: "description"},
115
+ createDom("a", {title: result.fullName, href: specHref(result)}, result.fullName)
116
+ ),
117
+ createDom("div", {className: "messages"})
118
+ );
119
+ var messages = failure.childNodes[1];
120
+
121
+ for (var i = 0; i < result.failedExpectations.length; i++) {
122
+ var expectation = result.failedExpectations[i];
123
+ messages.appendChild(createDom("div", {className: "result-message"}, expectation.message));
124
+ messages.appendChild(createDom("div", {className: "stack-trace"}, expectation.stack));
125
+ }
126
+
127
+ failures.push(failure);
128
+ }
129
+
130
+ if (result.status == "pending") {
131
+ pendingSpecCount++;
132
+ }
133
+ };
134
+
135
+ this.jasmineDone = function() {
136
+ var banner = find(".banner");
137
+ banner.appendChild(createDom("span", {className: "duration"}, "finished in " + timer.elapsed() / 1000 + "s"));
138
+
139
+ var alert = find(".alert");
140
+
141
+ alert.appendChild(createDom("span", { className: "exceptions" },
142
+ createDom("label", { className: "label", 'for': "raise-exceptions" }, "raise exceptions"),
143
+ createDom("input", {
144
+ className: "raise",
145
+ id: "raise-exceptions",
146
+ type: "checkbox"
147
+ })
148
+ ));
149
+ var checkbox = find("input");
150
+
151
+ checkbox.checked = !env.catchingExceptions();
152
+ checkbox.onclick = onRaiseExceptionsClick;
153
+
154
+ if (specsExecuted < totalSpecsDefined) {
155
+ var skippedMessage = "Ran " + specsExecuted + " of " + totalSpecsDefined + " specs - run all";
156
+ alert.appendChild(
157
+ createDom("span", {className: "bar skipped"},
158
+ createDom("a", {href: "?", title: "Run all specs"}, skippedMessage)
159
+ )
160
+ );
161
+ }
162
+ var statusBarMessage = "" + pluralize("spec", specsExecuted) + ", " + pluralize("failure", failureCount);
163
+ if (pendingSpecCount) { statusBarMessage += ", " + pluralize("pending spec", pendingSpecCount); }
164
+
165
+ var statusBarClassName = "bar " + ((failureCount > 0) ? "failed" : "passed");
166
+ alert.appendChild(createDom("span", {className: statusBarClassName}, statusBarMessage));
167
+
168
+ var results = find(".results");
169
+ results.appendChild(summary);
170
+
171
+ summaryList(topResults, summary);
172
+
173
+ function summaryList(resultsTree, domParent) {
174
+ var specListNode;
175
+ for (var i = 0; i < resultsTree.children.length; i++) {
176
+ var resultNode = resultsTree.children[i];
177
+ if (resultNode.type == "suite") {
178
+ var suiteListNode = createDom("ul", {className: "suite", id: "suite-" + resultNode.result.id},
179
+ createDom("li", {className: "suite-detail"},
180
+ createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
181
+ )
182
+ );
183
+
184
+ summaryList(resultNode, suiteListNode);
185
+ domParent.appendChild(suiteListNode);
186
+ }
187
+ if (resultNode.type == "spec") {
188
+ if (domParent.getAttribute("class") != "specs") {
189
+ specListNode = createDom("ul", {className: "specs"});
190
+ domParent.appendChild(specListNode);
191
+ }
192
+ specListNode.appendChild(
193
+ createDom("li", {
194
+ className: resultNode.result.status,
195
+ id: "spec-" + resultNode.result.id
196
+ },
197
+ createDom("a", {href: specHref(resultNode.result)}, resultNode.result.description)
198
+ )
199
+ );
200
+ }
201
+ }
202
+ }
203
+
204
+ if (failures.length) {
205
+ alert.appendChild(
206
+ createDom('span', {className: "menu bar spec-list"},
207
+ createDom("span", {}, "Spec List | "),
208
+ createDom('a', {className: "failures-menu", href: "#"}, "Failures")));
209
+ alert.appendChild(
210
+ createDom('span', {className: "menu bar failure-list"},
211
+ createDom('a', {className: "spec-list-menu", href: "#"}, "Spec List"),
212
+ createDom("span", {}, " | Failures ")));
213
+
214
+ find(".failures-menu").onclick = function() {
215
+ setMenuModeTo('failure-list');
216
+ };
217
+ find(".spec-list-menu").onclick = function() {
218
+ setMenuModeTo('spec-list');
219
+ };
220
+
221
+ setMenuModeTo('failure-list');
222
+
223
+ var failureNode = find(".failures");
224
+ for (var i = 0; i < failures.length; i++) {
225
+ failureNode.appendChild(failures[i]);
226
+ }
227
+ }
228
+ };
229
+
230
+ return this;
231
+
232
+ function find(selector) {
233
+ return getContainer().querySelector(selector);
234
+ }
235
+
236
+ function createDom(type, attrs, childrenVarArgs) {
237
+ var el = createElement(type);
238
+
239
+ for (var i = 2; i < arguments.length; i++) {
240
+ var child = arguments[i];
241
+
242
+ if (typeof child === 'string') {
243
+ el.appendChild(createTextNode(child));
244
+ } else {
245
+ if (child) {
246
+ el.appendChild(child);
247
+ }
248
+ }
249
+ }
250
+
251
+ for (var attr in attrs) {
252
+ if (attr == "className") {
253
+ el[attr] = attrs[attr];
254
+ } else {
255
+ el.setAttribute(attr, attrs[attr]);
256
+ }
257
+ }
258
+
259
+ return el;
260
+ }
261
+
262
+ function pluralize(singular, count) {
263
+ var word = (count == 1 ? singular : singular + "s");
264
+
265
+ return "" + count + " " + word;
266
+ }
267
+
268
+ function specHref(result) {
269
+ return "?spec=" + encodeURIComponent(result.fullName);
270
+ }
271
+
272
+ function setMenuModeTo(mode) {
273
+ htmlReporterMain.setAttribute("class", "html-reporter " + mode);
274
+ }
275
+ }
276
+
277
+ return HtmlReporter;
278
+ };
279
+
280
+ jasmineRequire.HtmlSpecFilter = function() {
281
+ function HtmlSpecFilter(options) {
282
+ var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
283
+ var filterPattern = new RegExp(filterString);
284
+
285
+ this.matches = function(specName) {
286
+ return filterPattern.test(specName);
287
+ };
288
+ }
289
+
290
+ return HtmlSpecFilter;
291
+ };
292
+
293
+ jasmineRequire.ResultsNode = function() {
294
+ function ResultsNode(result, type, parent) {
295
+ this.result = result;
296
+ this.type = type;
297
+ this.parent = parent;
298
+
299
+ this.children = [];
300
+
301
+ this.addChild = function(result, type) {
302
+ this.children.push(new ResultsNode(result, type, this));
303
+ };
304
+
305
+ this.last = function() {
306
+ return this.children[this.children.length - 1];
307
+ };
308
+ }
309
+
310
+ return ResultsNode;
311
+ };
312
+
313
+ jasmineRequire.QueryString = function() {
314
+ function QueryString(options) {
315
+
316
+ this.setParam = function(key, value) {
317
+ var paramMap = queryStringToParamMap();
318
+ paramMap[key] = value;
319
+ options.getWindowLocation().search = toQueryString(paramMap);
320
+ };
321
+
322
+ this.getParam = function(key) {
323
+ return queryStringToParamMap()[key];
324
+ };
325
+
326
+ return this;
327
+
328
+ function toQueryString(paramMap) {
329
+ var qStrPairs = [];
330
+ for (var prop in paramMap) {
331
+ qStrPairs.push(encodeURIComponent(prop) + "=" + encodeURIComponent(paramMap[prop]));
332
+ }
333
+ return "?" + qStrPairs.join('&');
334
+ }
335
+
336
+ function queryStringToParamMap() {
337
+ var paramStr = options.getWindowLocation().search.substring(1),
338
+ params = [],
339
+ paramMap = {};
340
+
341
+ if (paramStr.length > 0) {
342
+ params = paramStr.split('&');
343
+ for (var i = 0; i < params.length; i++) {
344
+ var p = params[i].split('=');
345
+ var value = decodeURIComponent(p[1]);
346
+ if (value === "true" || value === "false") {
347
+ value = JSON.parse(value);
348
+ }
349
+ paramMap[decodeURIComponent(p[0])] = value;
350
+ }
351
+ }
352
+
353
+ return paramMap;
354
+ }
355
+
356
+ }
357
+
358
+ return QueryString;
359
+ };
360
+