rspec-jasmine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rspec-jasmine.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Chris Kowalik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # RSpec::Jasmine
2
+
3
+ This is a nice and handy, RSpec powered runner and reporter for Jasmine
4
+ test suites. It's simpler and more flexible than stuff provided by `jasmine`
5
+ gem.
6
+
7
+ NOTE: It works only with RSpec 2.0 and higher.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'rspec-jasmine'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install rspec-jasmine
22
+
23
+ ## Usage
24
+
25
+ Check the example folder, it's the simples setup of `rspec-jasmine` together
26
+ with dummy Sinatra app. The most important files to check are `spec/jasmine.rb`,
27
+ `public/tests.html` and `Rakefile`. To run your tests use rake task:
28
+
29
+ $ rake spec:jasmine
30
+
31
+ You'll get nice output, formatted with your favorite RSpec formatter.
32
+
33
+ Probably I should write a generator for this stuff, but so far this is used only
34
+ in one project so I'm too lazy for it. If you have spare time you can do so
35
+ and send me a pull request.
36
+
37
+ ## Contributing
38
+
39
+ 1. Fork it
40
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
41
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
42
+ 4. Push to the branch (`git push origin my-new-feature`)
43
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
data/example/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/example/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source :rubygems
2
+
3
+ gem 'thin'
4
+ gem 'rake'
5
+ gem 'sinatra'
6
+ gem 'rspec', '>= 2.0'
7
+ gem 'rspec-jasmine', :path => '..'
data/example/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # Example app using RSpec::Jasmine
2
+
3
+ This is dummy sinatra application with some spec examples.
4
+
5
+ ## Usage
6
+
7
+ Install dependencies with Bundler:
8
+
9
+ $ bundle install
10
+
11
+ Run test suite:
12
+
13
+ $ rake spec:jasmine
14
+
15
+ Enjoy!
16
+
17
+ NOTE: Yeap, one example is failing, it's fine - so you can see how
18
+ `rspec-jasmine` handles failed examples.
data/example/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ desc 'Default: run specs.'
4
+ task :default => :spec
5
+
6
+ desc "Run specs"
7
+ RSpec::Core::RakeTask.new do |t|
8
+ end
9
+
10
+ namespace :spec do
11
+ desc "Runs jasmine specs"
12
+ task :jasmine do
13
+ require File.expand_path('../spec/jasmine', __FILE__)
14
+ end
15
+
16
+ desc "Run all test suites"
17
+ task :all => [:spec, :'spec:jasmine']
18
+ end
data/example/config.ru ADDED
@@ -0,0 +1,5 @@
1
+ require 'sinatra'
2
+
3
+ set :public_folder, File.expand_path('../public', __FILE__)
4
+
5
+ run Sinatra::Application
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2011 Pivotal Labs
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,616 @@
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
+
61
+ jasmine.HtmlReporter = function(_doc) {
62
+ var self = this;
63
+ var doc = _doc || window.document;
64
+
65
+ var reporterView;
66
+
67
+ var dom = {};
68
+
69
+ // Jasmine Reporter Public Interface
70
+ self.logRunningSpecs = false;
71
+
72
+ self.reportRunnerStarting = function(runner) {
73
+ var specs = runner.specs() || [];
74
+
75
+ if (specs.length == 0) {
76
+ return;
77
+ }
78
+
79
+ createReporterDom(runner.env.versionString());
80
+ doc.body.appendChild(dom.reporter);
81
+
82
+ reporterView = new jasmine.HtmlReporter.ReporterView(dom);
83
+ reporterView.addSpecs(specs, self.specFilter);
84
+ };
85
+
86
+ self.reportRunnerResults = function(runner) {
87
+ reporterView && reporterView.complete();
88
+ };
89
+
90
+ self.reportSuiteResults = function(suite) {
91
+ reporterView.suiteComplete(suite);
92
+ };
93
+
94
+ self.reportSpecStarting = function(spec) {
95
+ if (self.logRunningSpecs) {
96
+ self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
97
+ }
98
+ };
99
+
100
+ self.reportSpecResults = function(spec) {
101
+ reporterView.specComplete(spec);
102
+ };
103
+
104
+ self.log = function() {
105
+ var console = jasmine.getGlobal().console;
106
+ if (console && console.log) {
107
+ if (console.log.apply) {
108
+ console.log.apply(console, arguments);
109
+ } else {
110
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
111
+ }
112
+ }
113
+ };
114
+
115
+ self.specFilter = function(spec) {
116
+ if (!focusedSpecName()) {
117
+ return true;
118
+ }
119
+
120
+ return spec.getFullName().indexOf(focusedSpecName()) === 0;
121
+ };
122
+
123
+ return self;
124
+
125
+ function focusedSpecName() {
126
+ var specName;
127
+
128
+ (function memoizeFocusedSpec() {
129
+ if (specName) {
130
+ return;
131
+ }
132
+
133
+ var paramMap = [];
134
+ var params = doc.location.search.substring(1).split('&');
135
+
136
+ for (var i = 0; i < params.length; i++) {
137
+ var p = params[i].split('=');
138
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
139
+ }
140
+
141
+ specName = paramMap.spec;
142
+ })();
143
+
144
+ return specName;
145
+ }
146
+
147
+ function createReporterDom(version) {
148
+ dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
149
+ dom.banner = self.createDom('div', { className: 'banner' },
150
+ self.createDom('span', { className: 'title' }, "Jasmine "),
151
+ self.createDom('span', { className: 'version' }, version)),
152
+
153
+ dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
154
+ dom.alert = self.createDom('div', {className: 'alert'}),
155
+ dom.results = self.createDom('div', {className: 'results'},
156
+ dom.summary = self.createDom('div', { className: 'summary' }),
157
+ dom.details = self.createDom('div', { id: 'details' }))
158
+ );
159
+ }
160
+ };
161
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
162
+ this.startedAt = new Date();
163
+ this.runningSpecCount = 0;
164
+ this.completeSpecCount = 0;
165
+ this.passedCount = 0;
166
+ this.failedCount = 0;
167
+ this.skippedCount = 0;
168
+
169
+ this.createResultsMenu = function() {
170
+ this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
171
+ this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
172
+ ' | ',
173
+ this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
174
+
175
+ this.summaryMenuItem.onclick = function() {
176
+ dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
177
+ };
178
+
179
+ this.detailsMenuItem.onclick = function() {
180
+ showDetails();
181
+ };
182
+ };
183
+
184
+ this.addSpecs = function(specs, specFilter) {
185
+ this.totalSpecCount = specs.length;
186
+
187
+ this.views = {
188
+ specs: {},
189
+ suites: {}
190
+ };
191
+
192
+ for (var i = 0; i < specs.length; i++) {
193
+ var spec = specs[i];
194
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
195
+ if (specFilter(spec)) {
196
+ this.runningSpecCount++;
197
+ }
198
+ }
199
+ };
200
+
201
+ this.specComplete = function(spec) {
202
+ this.completeSpecCount++;
203
+
204
+ if (isUndefined(this.views.specs[spec.id])) {
205
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
206
+ }
207
+
208
+ var specView = this.views.specs[spec.id];
209
+
210
+ switch (specView.status()) {
211
+ case 'passed':
212
+ this.passedCount++;
213
+ break;
214
+
215
+ case 'failed':
216
+ this.failedCount++;
217
+ break;
218
+
219
+ case 'skipped':
220
+ this.skippedCount++;
221
+ break;
222
+ }
223
+
224
+ specView.refresh();
225
+ this.refresh();
226
+ };
227
+
228
+ this.suiteComplete = function(suite) {
229
+ var suiteView = this.views.suites[suite.id];
230
+ if (isUndefined(suiteView)) {
231
+ return;
232
+ }
233
+ suiteView.refresh();
234
+ };
235
+
236
+ this.refresh = function() {
237
+
238
+ if (isUndefined(this.resultsMenu)) {
239
+ this.createResultsMenu();
240
+ }
241
+
242
+ // currently running UI
243
+ if (isUndefined(this.runningAlert)) {
244
+ this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
245
+ dom.alert.appendChild(this.runningAlert);
246
+ }
247
+ this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
248
+
249
+ // skipped specs UI
250
+ if (isUndefined(this.skippedAlert)) {
251
+ this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
252
+ }
253
+
254
+ this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
255
+
256
+ if (this.skippedCount === 1 && isDefined(dom.alert)) {
257
+ dom.alert.appendChild(this.skippedAlert);
258
+ }
259
+
260
+ // passing specs UI
261
+ if (isUndefined(this.passedAlert)) {
262
+ this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
263
+ }
264
+ this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
265
+
266
+ // failing specs UI
267
+ if (isUndefined(this.failedAlert)) {
268
+ this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
269
+ }
270
+ this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
271
+
272
+ if (this.failedCount === 1 && isDefined(dom.alert)) {
273
+ dom.alert.appendChild(this.failedAlert);
274
+ dom.alert.appendChild(this.resultsMenu);
275
+ }
276
+
277
+ // summary info
278
+ this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
279
+ this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
280
+ };
281
+
282
+ this.complete = function() {
283
+ dom.alert.removeChild(this.runningAlert);
284
+
285
+ this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
286
+
287
+ if (this.failedCount === 0) {
288
+ dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
289
+ } else {
290
+ showDetails();
291
+ }
292
+
293
+ dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
294
+ };
295
+
296
+ return this;
297
+
298
+ function showDetails() {
299
+ if (dom.reporter.className.search(/showDetails/) === -1) {
300
+ dom.reporter.className += " showDetails";
301
+ }
302
+ }
303
+
304
+ function isUndefined(obj) {
305
+ return typeof obj === 'undefined';
306
+ }
307
+
308
+ function isDefined(obj) {
309
+ return !isUndefined(obj);
310
+ }
311
+
312
+ function specPluralizedFor(count) {
313
+ var str = count + " spec";
314
+ if (count > 1) {
315
+ str += "s"
316
+ }
317
+ return str;
318
+ }
319
+
320
+ };
321
+
322
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
323
+
324
+
325
+ jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
326
+ this.spec = spec;
327
+ this.dom = dom;
328
+ this.views = views;
329
+
330
+ this.symbol = this.createDom('li', { className: 'pending' });
331
+ this.dom.symbolSummary.appendChild(this.symbol);
332
+
333
+ this.summary = this.createDom('div', { className: 'specSummary' },
334
+ this.createDom('a', {
335
+ className: 'description',
336
+ href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
337
+ title: this.spec.getFullName()
338
+ }, this.spec.description)
339
+ );
340
+
341
+ this.detail = this.createDom('div', { className: 'specDetail' },
342
+ this.createDom('a', {
343
+ className: 'description',
344
+ href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
345
+ title: this.spec.getFullName()
346
+ }, this.spec.getFullName())
347
+ );
348
+ };
349
+
350
+ jasmine.HtmlReporter.SpecView.prototype.status = function() {
351
+ return this.getSpecStatus(this.spec);
352
+ };
353
+
354
+ jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
355
+ this.symbol.className = this.status();
356
+
357
+ switch (this.status()) {
358
+ case 'skipped':
359
+ break;
360
+
361
+ case 'passed':
362
+ this.appendSummaryToSuiteDiv();
363
+ break;
364
+
365
+ case 'failed':
366
+ this.appendSummaryToSuiteDiv();
367
+ this.appendFailureDetail();
368
+ break;
369
+ }
370
+ };
371
+
372
+ jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
373
+ this.summary.className += ' ' + this.status();
374
+ this.appendToSummary(this.spec, this.summary);
375
+ };
376
+
377
+ jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
378
+ this.detail.className += ' ' + this.status();
379
+
380
+ var resultItems = this.spec.results().getItems();
381
+ var messagesDiv = this.createDom('div', { className: 'messages' });
382
+
383
+ for (var i = 0; i < resultItems.length; i++) {
384
+ var result = resultItems[i];
385
+
386
+ if (result.type == 'log') {
387
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
388
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
389
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
390
+
391
+ if (result.trace.stack) {
392
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
393
+ }
394
+ }
395
+ }
396
+
397
+ if (messagesDiv.childNodes.length > 0) {
398
+ this.detail.appendChild(messagesDiv);
399
+ this.dom.details.appendChild(this.detail);
400
+ }
401
+ };
402
+
403
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
404
+ this.suite = suite;
405
+ this.dom = dom;
406
+ this.views = views;
407
+
408
+ this.element = this.createDom('div', { className: 'suite' },
409
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
410
+ );
411
+
412
+ this.appendToSummary(this.suite, this.element);
413
+ };
414
+
415
+ jasmine.HtmlReporter.SuiteView.prototype.status = function() {
416
+ return this.getSpecStatus(this.suite);
417
+ };
418
+
419
+ jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
420
+ this.element.className += " " + this.status();
421
+ };
422
+
423
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
424
+
425
+ /* @deprecated Use jasmine.HtmlReporter instead
426
+ */
427
+ jasmine.TrivialReporter = function(doc) {
428
+ this.document = doc || document;
429
+ this.suiteDivs = {};
430
+ this.logRunningSpecs = false;
431
+ };
432
+
433
+ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
434
+ var el = document.createElement(type);
435
+
436
+ for (var i = 2; i < arguments.length; i++) {
437
+ var child = arguments[i];
438
+
439
+ if (typeof child === 'string') {
440
+ el.appendChild(document.createTextNode(child));
441
+ } else {
442
+ if (child) { el.appendChild(child); }
443
+ }
444
+ }
445
+
446
+ for (var attr in attrs) {
447
+ if (attr == "className") {
448
+ el[attr] = attrs[attr];
449
+ } else {
450
+ el.setAttribute(attr, attrs[attr]);
451
+ }
452
+ }
453
+
454
+ return el;
455
+ };
456
+
457
+ jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
458
+ var showPassed, showSkipped;
459
+
460
+ this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
461
+ this.createDom('div', { className: 'banner' },
462
+ this.createDom('div', { className: 'logo' },
463
+ this.createDom('span', { className: 'title' }, "Jasmine"),
464
+ this.createDom('span', { className: 'version' }, runner.env.versionString())),
465
+ this.createDom('div', { className: 'options' },
466
+ "Show ",
467
+ showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
468
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
469
+ showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
470
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
471
+ )
472
+ ),
473
+
474
+ this.runnerDiv = this.createDom('div', { className: 'runner running' },
475
+ this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
476
+ this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
477
+ this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
478
+ );
479
+
480
+ this.document.body.appendChild(this.outerDiv);
481
+
482
+ var suites = runner.suites();
483
+ for (var i = 0; i < suites.length; i++) {
484
+ var suite = suites[i];
485
+ var suiteDiv = this.createDom('div', { className: 'suite' },
486
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
487
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
488
+ this.suiteDivs[suite.id] = suiteDiv;
489
+ var parentDiv = this.outerDiv;
490
+ if (suite.parentSuite) {
491
+ parentDiv = this.suiteDivs[suite.parentSuite.id];
492
+ }
493
+ parentDiv.appendChild(suiteDiv);
494
+ }
495
+
496
+ this.startedAt = new Date();
497
+
498
+ var self = this;
499
+ showPassed.onclick = function(evt) {
500
+ if (showPassed.checked) {
501
+ self.outerDiv.className += ' show-passed';
502
+ } else {
503
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
504
+ }
505
+ };
506
+
507
+ showSkipped.onclick = function(evt) {
508
+ if (showSkipped.checked) {
509
+ self.outerDiv.className += ' show-skipped';
510
+ } else {
511
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
512
+ }
513
+ };
514
+ };
515
+
516
+ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
517
+ var results = runner.results();
518
+ var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
519
+ this.runnerDiv.setAttribute("class", className);
520
+ //do it twice for IE
521
+ this.runnerDiv.setAttribute("className", className);
522
+ var specs = runner.specs();
523
+ var specCount = 0;
524
+ for (var i = 0; i < specs.length; i++) {
525
+ if (this.specFilter(specs[i])) {
526
+ specCount++;
527
+ }
528
+ }
529
+ var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
530
+ message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
531
+ this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
532
+
533
+ this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
534
+ };
535
+
536
+ jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
537
+ var results = suite.results();
538
+ var status = results.passed() ? 'passed' : 'failed';
539
+ if (results.totalCount === 0) { // todo: change this to check results.skipped
540
+ status = 'skipped';
541
+ }
542
+ this.suiteDivs[suite.id].className += " " + status;
543
+ };
544
+
545
+ jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
546
+ if (this.logRunningSpecs) {
547
+ this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
548
+ }
549
+ };
550
+
551
+ jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
552
+ var results = spec.results();
553
+ var status = results.passed() ? 'passed' : 'failed';
554
+ if (results.skipped) {
555
+ status = 'skipped';
556
+ }
557
+ var specDiv = this.createDom('div', { className: 'spec ' + status },
558
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
559
+ this.createDom('a', {
560
+ className: 'description',
561
+ href: '?spec=' + encodeURIComponent(spec.getFullName()),
562
+ title: spec.getFullName()
563
+ }, spec.description));
564
+
565
+
566
+ var resultItems = results.getItems();
567
+ var messagesDiv = this.createDom('div', { className: 'messages' });
568
+ for (var i = 0; i < resultItems.length; i++) {
569
+ var result = resultItems[i];
570
+
571
+ if (result.type == 'log') {
572
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
573
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
574
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
575
+
576
+ if (result.trace.stack) {
577
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
578
+ }
579
+ }
580
+ }
581
+
582
+ if (messagesDiv.childNodes.length > 0) {
583
+ specDiv.appendChild(messagesDiv);
584
+ }
585
+
586
+ this.suiteDivs[spec.suite.id].appendChild(specDiv);
587
+ };
588
+
589
+ jasmine.TrivialReporter.prototype.log = function() {
590
+ var console = jasmine.getGlobal().console;
591
+ if (console && console.log) {
592
+ if (console.log.apply) {
593
+ console.log.apply(console, arguments);
594
+ } else {
595
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
596
+ }
597
+ }
598
+ };
599
+
600
+ jasmine.TrivialReporter.prototype.getLocation = function() {
601
+ return this.document.location;
602
+ };
603
+
604
+ jasmine.TrivialReporter.prototype.specFilter = function(spec) {
605
+ var paramMap = {};
606
+ var params = this.getLocation().search.substring(1).split('&');
607
+ for (var i = 0; i < params.length; i++) {
608
+ var p = params[i].split('=');
609
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
610
+ }
611
+
612
+ if (!paramMap.spec) {
613
+ return true;
614
+ }
615
+ return spec.getFullName().indexOf(paramMap.spec) === 0;
616
+ };