brainsome_jasminerice 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 749f7baa9d005a8129dc028c7c228507e7c37b01
4
+ data.tar.gz: 7ff340abb8ae87df3419c71a6c0eab8b0722a9cd
5
+ SHA512:
6
+ metadata.gz: 052cf2a1a9d97e2999cf031b43893d4df592065e3a806568faf834a27975f8e2b392984566a2ca51aeb3a1750b833c7acc998a751f56796c7725162bf9e137f3
7
+ data.tar.gz: 2fd50ee216f9d0ffd9703ecc4e19ffc57787f79624783d63ab9af88f2d5f7cfcbcf830bda46c716fb9cb13eff5ed8a30b59c8f4566253e02adbadefdeab559b4
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Brad Phelan
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,190 @@
1
+ Jasminerice
2
+ ===========
3
+
4
+ Utilizing [Jasmine](http://pivotal.github.com/jasmine/) and taking full advantage of the Rails 3.1 asset pipeline Jasminerice removes any excuse YOU have for not testing your out of control sprawl of CoffeeScript files.
5
+
6
+ This project rocks and uses the MIT-LICENSE.
7
+
8
+
9
+ ## Development Notice
10
+
11
+ Brad Phelan is no longer actively developing this project but is accepting reasonable pull requests, so continue on with contributing.
12
+
13
+ This project is looking for a home :)
14
+
15
+ #### 2013/1/17:
16
+ Brad ([bradphelan](https://github.com/bradphelan)) posted a notice saying that he wasn't actively maintaining the project and that it was looking for a home.
17
+
18
+ #### 2013/1/27:
19
+ I ([jejacks0n](https://github.com/jejacks0n)) offered to contribute to the project, and Brad granted me collaboration privileges. I added some specs and integration tests that will make contributing a little easier.
20
+
21
+ We'll be managing pull requests and issues together, and if someone would like to take over and move it to a different home you should contact Brad directly.
22
+
23
+
24
+ ## Headless Testing
25
+
26
+ See [guard-jasmine](https://github.com/netzpirat/guard-jasmine) for details.
27
+
28
+
29
+ ## Installation
30
+
31
+ This gem has been tested and run with Rails 3.1 and 3.2. It should also run on Rails 4.
32
+
33
+ Just include it in your `Gemfile`:
34
+
35
+ ```ruby
36
+ group :development, :test do
37
+ gem "jasminerice", :git => 'https://github.com/bradphelan/jasminerice.git'
38
+ end
39
+ ```
40
+
41
+ The engine is automatically mounted into your application in the development and test environments. If you'd like to change that behavior, you can change which groups the gem is included in via the gemfile.
42
+
43
+ Optionally, you can run the installer.
44
+
45
+ ```bash
46
+ rails g jasminerice:install
47
+ ```
48
+
49
+ This will add the required `spec.js.coffee`, an example spec, and fixture to help get you started. It will also add a intializer `config/initializers/jasminerice.rb` which can be used for easy setup of Jasminerice's options.
50
+
51
+
52
+ ## Usage
53
+
54
+ ### CoffeeScripts
55
+
56
+ Create a file `spec/javascripts/spec.js.coffee` (or run the install generator), and add the following content.
57
+
58
+ ```coffeescript
59
+ #= require_tree ./
60
+ ```
61
+
62
+ In the case where you need access to all your application javascripts then you can use something like the following, which will pull in all the files from your application and all specs from the `javascripts` directory.
63
+
64
+ ```coffeescript
65
+ #= require_tree ./
66
+ #= require_tree ../../app/assets/javascripts
67
+ ```
68
+
69
+ The Rails 3.1 asset pipeline using [Sprockets](https://github.com/sstephenson/sprockets) and [Tilt](https://github.com/rtomayko/tilt) ensure conversion to javascript.
70
+
71
+ You can also use the `#= require` directive in your specs to pull in dependencies manually. Here's an example `spec/javascripts/example_spec.js.coffee`:
72
+
73
+ ```coffeescript
74
+ #= require foo
75
+ #= require bar
76
+
77
+ describe "Foo", ->
78
+ it "it is not bar", ->
79
+ v = new Foo()
80
+ expect(v.bar()).toEqual(false)
81
+
82
+ describe "Bar", ->
83
+ it "it is not foo", ->
84
+ v = new Bar()
85
+ expect(v.foo()).toEqual(false)
86
+ ```
87
+
88
+ ### Stylesheets
89
+
90
+ For including stylesheets in your specs, Jasminerice uses `spec/javascripts/spec.css`. You can use Sprockets directives to include css files here.
91
+
92
+ ```css
93
+ /*= require application
94
+ */
95
+ ```
96
+
97
+ ### Fixtures
98
+
99
+ Jasminerice makes files located in the `spec/javascripts/fixtures` directory available as fixture. For example, if you put a file named `example_fixture.html.haml` in that path it will be available at the `/jasmine/fixtures/example_fixture` URL.
100
+
101
+ spec/javascripts/fixtures/example_fixture.html.haml
102
+ ```haml
103
+ %h2 Test Fixture
104
+ %p Using fixtures
105
+ ```
106
+
107
+ Since Jasminerice automatically makes a patched version of [jasmine-jquery](https://github.com/velesin/jasmine-jquery) available in your specs, you can load the example fixture in your spec with the following.
108
+
109
+ ```javascript
110
+ loadFixtures('example_fixture')
111
+ ```
112
+
113
+ You can also load JSON fixtures, e.g. `spec/javascripts/fixtures/json/bar.json`
114
+
115
+ ```javascript
116
+ getJSONFixture('bar')
117
+ ```
118
+
119
+ ### Helper Methods
120
+
121
+ You can declare Jasminerice::SpecHelper (perhaps put inside lib/) to make helpers available to jasminerice fixtures.
122
+
123
+ So in your lib directory, create the helper, e.g. `lib/jasminerice/spec_helper.rb`
124
+
125
+ ```ruby
126
+ module Jasminerice
127
+ module SpecHelper
128
+ def print_a_test
129
+ "foo"
130
+ end
131
+ end
132
+ end
133
+ ```
134
+
135
+ Then you can use it in your fixtures.
136
+
137
+ spec/javascripts/fixtures/example_fixture.html.haml
138
+ ```haml
139
+ %h1 Here is my helper
140
+ = print_a_test
141
+ ```
142
+
143
+ ### Running Specs
144
+
145
+ Start your server...
146
+
147
+ ```bash
148
+ rails s
149
+ ```
150
+
151
+ Browse to...
152
+
153
+ ```
154
+ http://localhost:3000/jasmine
155
+ ```
156
+
157
+ Watch your specs run.
158
+
159
+ ### Asset debugging
160
+
161
+ You can override your current environment's `config.assets.debug` configuration per request by adding `?debug=false` or `?debug=true` to the jasmine path, eg.
162
+
163
+ ```
164
+ http://localhost:3000/jasmine?debug=false
165
+ ```
166
+
167
+ This will concatenate all your css and javascript into single file which can improve your suite's loading speed significantly.
168
+
169
+ ### Compatibility with Require.js
170
+
171
+ If you use [Require.js](http://requirejs.org/) in your project and need to load your modules in your jasmine specs, there is an option to prevent jasminerice from automatically executing the test runner before the modules are defined. This enables you to start the execution manually whenever you want in your `spec/javascripts/spec.js.coffee` file:
172
+
173
+ ```coffeescript
174
+ #= require your/specs/and/other/stuff
175
+ # at the end of this file add:
176
+
177
+ jasmine.rice.autoExecute = false
178
+
179
+ define 'jasmine.waitsfor.requirejs', ->
180
+ require ['jasmine.waitsfor.requirejs'], jasmine.getEnv().execute
181
+ ```
182
+
183
+ The shown example defines a dummy module in require.js that is required immediately on the next line. This is a simple hack to wait until require.js has initialized all modules and start the jasmine runner after that.
184
+
185
+ Of course you can use `jasmine.rice.autoExecute = false` also for all other cases where you need to control when your specs should be executed!
186
+
187
+
188
+ ## Author
189
+
190
+ * Brad Phelan (bradphelan@xtargets.com)
@@ -0,0 +1,32 @@
1
+ #=require jasmine
2
+ #=require jasmine-html
3
+ #=require jasmine-jquery-1.5.8
4
+
5
+ (->
6
+ execJasmine = ->
7
+ jasmineEnv.execute()
8
+ jasmineEnv = jasmine.getEnv()
9
+ jasmineEnv.updateInterval = 1000
10
+
11
+ window.jsApiReporter = new jasmine.JsApiReporter()
12
+ htmlReporter = new jasmine.HtmlReporter()
13
+
14
+ jasmineEnv.addReporter htmlReporter
15
+ jasmineEnv.addReporter jsApiReporter
16
+
17
+ jasmineEnv.specFilter = (spec) ->
18
+ htmlReporter.specFilter spec
19
+
20
+ jasmine.getFixtures().fixturesPath = 'jasmine/fixtures'
21
+ jasmine.getStyleFixtures().fixturesPath = 'jasmine/fixtures'
22
+ jasmine.getJSONFixtures().fixturesPath = 'jasmine/fixtures/json'
23
+
24
+ jasmine.rice = {}
25
+ jasmine.rice.autoExecute = true
26
+
27
+ currentWindowOnload = window.onload
28
+ window.onload = ->
29
+ currentWindowOnload() if currentWindowOnload
30
+ if jasmine.rice.autoExecute
31
+ execJasmine()
32
+ )()
@@ -0,0 +1,4 @@
1
+ module Jasminerice
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,22 @@
1
+ module Jasminerice
2
+ class SpecController < Jasminerice::ApplicationController
3
+ warn "Using Jasminerice::HelperMethods is deprecated and will be removed in a future release,"\
4
+ "please use Jasminerice::SpecHelper to define your helpers in the future" if defined?(Jasminerice::HelperMethods)
5
+
6
+ helper Jasminerice::HelperMethods rescue nil
7
+ helper Jasminerice::SpecHelper rescue nil
8
+
9
+ before_filter { prepend_view_path Rails.root.to_s }
10
+
11
+ layout false
12
+
13
+ def index
14
+ @specsuite = params[:suite].try(:concat, "_spec") || "spec"
15
+ @asset_options = %w(true false).include?(params[:debug]) ? { :debug => params[:debug] == 'true' } : {}
16
+ end
17
+
18
+ def fixtures
19
+ render "#{Jasminerice.fixture_path}/#{params[:filename]}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+ module Jasminerice
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Jasmine Spec Runner</title>
5
+ <%= stylesheet_link_tag "jasmine" %>
6
+ <%= stylesheet_link_tag "spec", @asset_options.clone %>
7
+ <%= javascript_include_tag "jasminerice" %>
8
+ <%= javascript_include_tag @specsuite, @asset_options.clone %>
9
+ <%= csrf_meta_tags %>
10
+ </head>
11
+ <body></body>
12
+ </html>
@@ -0,0 +1,7 @@
1
+ Jasminerice::Engine.routes.draw do
2
+ resources :spec, :controller => 'spec', :only => [:index] do
3
+ get "fixtures/*filename", :action => :fixtures
4
+ end
5
+ get "fixtures/*filename", :to => "spec#fixtures"
6
+ get "/(:suite)", :to => "spec#index"
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails'
2
+ if ::Rails.version >= '3.1'
3
+ module Jasminerice
4
+ module Generators
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ def copy_files
9
+ copy_file 'jasminerice.rb', 'config/initializers/jasminerice.rb'
10
+ copy_file 'spec.js.coffee', 'spec/javascripts/spec.js.coffee'
11
+ copy_file 'example_spec.js.coffee', 'spec/javascripts/example_spec.js.coffee'
12
+ copy_file 'spec.css', 'spec/javascripts/spec.css'
13
+ copy_file 'example_fixture.html.haml', 'spec/javascripts/fixtures/example_fixture.html.haml'
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,2 @@
1
+ %h2 Test Fixture
2
+ %p Using fixtures
@@ -0,0 +1,14 @@
1
+ # use require to load any .js file available to the asset pipeline
2
+ #= require foo
3
+ #= require bar
4
+
5
+ describe "Foo", ->
6
+ loadFixtures 'example_fixture' # located at 'spec/javascripts/fixtures/example_fixture.html.haml'
7
+ it "it is not bar", ->
8
+ v = new Foo()
9
+ expect(v.bar()).toEqual(false)
10
+
11
+ describe "Bar", ->
12
+ it "it is not foo", ->
13
+ v = new Bar()
14
+ expect(v.foo()).toEqual(false)
@@ -0,0 +1,19 @@
1
+ # Use this file to set configuration options for Jasminerice, all of these are initialized to their respective defaults,
2
+ # but you can change them here.
3
+ if defined?(Jasminerice) == 'constant'
4
+ Jasminerice.setup do |config|
5
+ # Tell Jasminerice to automatically mount itself in your application. If set to false, you must manually mount the
6
+ # engine in order to use Jasminerice.
7
+ #config.mount = true
8
+
9
+ # If automatically mounting Jasminerice, specify the location that it should be mounted at. Defaults to /jasmine, so
10
+ # you could access your tests at http://YOUR_SERVER_URL/jasmine
11
+ #config.mount_at = '/jasmine'
12
+
13
+ # Specify a path where your specs can be found. Defaults to 'spec'
14
+ #config.spec_path = 'spec'
15
+
16
+ # Specify a path where your fixutures can be found. Defaults to 'spec/javascripts/fixtures'
17
+ #config.fixture_path = 'spec/javascripts/fixtures'
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ /*
2
+ * Include the css files needed for javascript tests.
3
+ */
@@ -0,0 +1,7 @@
1
+ # This pulls in all your specs from the javascripts directory into Jasmine:
2
+ #
3
+ # spec/javascripts/*_spec.js.coffee
4
+ # spec/javascripts/*_spec.js
5
+ # spec/javascripts/*_spec.js.erb
6
+ #
7
+ #=require_tree ./
@@ -0,0 +1,38 @@
1
+ module Jasminerice
2
+ # Determine whether or not to mount the Jasminerice engine implicitly. True/False
3
+ mattr_accessor :mount
4
+ @@mount = true
5
+
6
+ # Specify location at which to mount the engine, default to '/jasmine'
7
+ mattr_accessor :mount_at
8
+ @@mount_at = '/jasmine'
9
+
10
+ # Specify the path for specs, defaults to 'spec'
11
+ mattr_accessor :spec_path
12
+ @@spec_path = 'spec'
13
+
14
+ #Specify the path for fixutures, defaults to 'spec/javascripts/fixtures'
15
+ mattr_accessor :fixture_path
16
+ @@fixture_path = 'spec/javascripts/fixtures'
17
+
18
+ # Default way to setup Jasminerice. Run rails generate jasminerice:install to create
19
+ # a fresh initializer with all configuration values.
20
+ def self.setup
21
+ yield self
22
+ end
23
+
24
+ class Engine < Rails::Engine
25
+ isolate_namespace Jasminerice
26
+
27
+ initializer :assets, :group => :all do |app|
28
+ app.config.assets.paths << Rails.root.join(Jasminerice.spec_path, "javascripts").to_s
29
+ app.config.assets.paths << Rails.root.join(Jasminerice.spec_path, "stylesheets").to_s
30
+ end
31
+
32
+ config.after_initialize do |app|
33
+ app.routes.prepend do
34
+ mount Jasminerice::Engine => Jasminerice.mount_at
35
+ end if Jasminerice.mount
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module Jasminerice
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,681 @@
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
+ setExceptionHandling();
82
+
83
+ reporterView = new jasmine.HtmlReporter.ReporterView(dom);
84
+ reporterView.addSpecs(specs, self.specFilter);
85
+ };
86
+
87
+ self.reportRunnerResults = function(runner) {
88
+ reporterView && reporterView.complete();
89
+ };
90
+
91
+ self.reportSuiteResults = function(suite) {
92
+ reporterView.suiteComplete(suite);
93
+ };
94
+
95
+ self.reportSpecStarting = function(spec) {
96
+ if (self.logRunningSpecs) {
97
+ self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
98
+ }
99
+ };
100
+
101
+ self.reportSpecResults = function(spec) {
102
+ reporterView.specComplete(spec);
103
+ };
104
+
105
+ self.log = function() {
106
+ var console = jasmine.getGlobal().console;
107
+ if (console && console.log) {
108
+ if (console.log.apply) {
109
+ console.log.apply(console, arguments);
110
+ } else {
111
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
112
+ }
113
+ }
114
+ };
115
+
116
+ self.specFilter = function(spec) {
117
+ if (!focusedSpecName()) {
118
+ return true;
119
+ }
120
+
121
+ return spec.getFullName().indexOf(focusedSpecName()) === 0;
122
+ };
123
+
124
+ return self;
125
+
126
+ function focusedSpecName() {
127
+ var specName;
128
+
129
+ (function memoizeFocusedSpec() {
130
+ if (specName) {
131
+ return;
132
+ }
133
+
134
+ var paramMap = [];
135
+ var params = jasmine.HtmlReporter.parameters(doc);
136
+
137
+ for (var i = 0; i < params.length; i++) {
138
+ var p = params[i].split('=');
139
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
140
+ }
141
+
142
+ specName = paramMap.spec;
143
+ })();
144
+
145
+ return specName;
146
+ }
147
+
148
+ function createReporterDom(version) {
149
+ dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
150
+ dom.banner = self.createDom('div', { className: 'banner' },
151
+ self.createDom('span', { className: 'title' }, "Jasmine "),
152
+ self.createDom('span', { className: 'version' }, version)),
153
+
154
+ dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
155
+ dom.alert = self.createDom('div', {className: 'alert'},
156
+ self.createDom('span', { className: 'exceptions' },
157
+ self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'),
158
+ self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
159
+ dom.results = self.createDom('div', {className: 'results'},
160
+ dom.summary = self.createDom('div', { className: 'summary' }),
161
+ dom.details = self.createDom('div', { id: 'details' }))
162
+ );
163
+ }
164
+
165
+ function noTryCatch() {
166
+ return window.location.search.match(/catch=false/);
167
+ }
168
+
169
+ function searchWithCatch() {
170
+ var params = jasmine.HtmlReporter.parameters(window.document);
171
+ var removed = false;
172
+ var i = 0;
173
+
174
+ while (!removed && i < params.length) {
175
+ if (params[i].match(/catch=/)) {
176
+ params.splice(i, 1);
177
+ removed = true;
178
+ }
179
+ i++;
180
+ }
181
+ if (jasmine.CATCH_EXCEPTIONS) {
182
+ params.push("catch=false");
183
+ }
184
+
185
+ return params.join("&");
186
+ }
187
+
188
+ function setExceptionHandling() {
189
+ var chxCatch = document.getElementById('no_try_catch');
190
+
191
+ if (noTryCatch()) {
192
+ chxCatch.setAttribute('checked', true);
193
+ jasmine.CATCH_EXCEPTIONS = false;
194
+ }
195
+ chxCatch.onclick = function() {
196
+ window.location.search = searchWithCatch();
197
+ };
198
+ }
199
+ };
200
+ jasmine.HtmlReporter.parameters = function(doc) {
201
+ var paramStr = doc.location.search.substring(1);
202
+ var params = [];
203
+
204
+ if (paramStr.length > 0) {
205
+ params = paramStr.split('&');
206
+ }
207
+ return params;
208
+ }
209
+ jasmine.HtmlReporter.sectionLink = function(sectionName) {
210
+ var link = '?';
211
+ var params = [];
212
+
213
+ if (sectionName) {
214
+ params.push('spec=' + encodeURIComponent(sectionName));
215
+ }
216
+ if (!jasmine.CATCH_EXCEPTIONS) {
217
+ params.push("catch=false");
218
+ }
219
+ if (params.length > 0) {
220
+ link += params.join("&");
221
+ }
222
+
223
+ return link;
224
+ };
225
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
226
+ jasmine.HtmlReporter.ReporterView = function(dom) {
227
+ this.startedAt = new Date();
228
+ this.runningSpecCount = 0;
229
+ this.completeSpecCount = 0;
230
+ this.passedCount = 0;
231
+ this.failedCount = 0;
232
+ this.skippedCount = 0;
233
+
234
+ this.createResultsMenu = function() {
235
+ this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
236
+ this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
237
+ ' | ',
238
+ this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
239
+
240
+ this.summaryMenuItem.onclick = function() {
241
+ dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
242
+ };
243
+
244
+ this.detailsMenuItem.onclick = function() {
245
+ showDetails();
246
+ };
247
+ };
248
+
249
+ this.addSpecs = function(specs, specFilter) {
250
+ this.totalSpecCount = specs.length;
251
+
252
+ this.views = {
253
+ specs: {},
254
+ suites: {}
255
+ };
256
+
257
+ for (var i = 0; i < specs.length; i++) {
258
+ var spec = specs[i];
259
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
260
+ if (specFilter(spec)) {
261
+ this.runningSpecCount++;
262
+ }
263
+ }
264
+ };
265
+
266
+ this.specComplete = function(spec) {
267
+ this.completeSpecCount++;
268
+
269
+ if (isUndefined(this.views.specs[spec.id])) {
270
+ this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
271
+ }
272
+
273
+ var specView = this.views.specs[spec.id];
274
+
275
+ switch (specView.status()) {
276
+ case 'passed':
277
+ this.passedCount++;
278
+ break;
279
+
280
+ case 'failed':
281
+ this.failedCount++;
282
+ break;
283
+
284
+ case 'skipped':
285
+ this.skippedCount++;
286
+ break;
287
+ }
288
+
289
+ specView.refresh();
290
+ this.refresh();
291
+ };
292
+
293
+ this.suiteComplete = function(suite) {
294
+ var suiteView = this.views.suites[suite.id];
295
+ if (isUndefined(suiteView)) {
296
+ return;
297
+ }
298
+ suiteView.refresh();
299
+ };
300
+
301
+ this.refresh = function() {
302
+
303
+ if (isUndefined(this.resultsMenu)) {
304
+ this.createResultsMenu();
305
+ }
306
+
307
+ // currently running UI
308
+ if (isUndefined(this.runningAlert)) {
309
+ this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
310
+ dom.alert.appendChild(this.runningAlert);
311
+ }
312
+ this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
313
+
314
+ // skipped specs UI
315
+ if (isUndefined(this.skippedAlert)) {
316
+ this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
317
+ }
318
+
319
+ this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
320
+
321
+ if (this.skippedCount === 1 && isDefined(dom.alert)) {
322
+ dom.alert.appendChild(this.skippedAlert);
323
+ }
324
+
325
+ // passing specs UI
326
+ if (isUndefined(this.passedAlert)) {
327
+ this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
328
+ }
329
+ this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
330
+
331
+ // failing specs UI
332
+ if (isUndefined(this.failedAlert)) {
333
+ this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
334
+ }
335
+ this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
336
+
337
+ if (this.failedCount === 1 && isDefined(dom.alert)) {
338
+ dom.alert.appendChild(this.failedAlert);
339
+ dom.alert.appendChild(this.resultsMenu);
340
+ }
341
+
342
+ // summary info
343
+ this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
344
+ this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
345
+ };
346
+
347
+ this.complete = function() {
348
+ dom.alert.removeChild(this.runningAlert);
349
+
350
+ this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
351
+
352
+ if (this.failedCount === 0) {
353
+ dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
354
+ } else {
355
+ showDetails();
356
+ }
357
+
358
+ dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
359
+ };
360
+
361
+ return this;
362
+
363
+ function showDetails() {
364
+ if (dom.reporter.className.search(/showDetails/) === -1) {
365
+ dom.reporter.className += " showDetails";
366
+ }
367
+ }
368
+
369
+ function isUndefined(obj) {
370
+ return typeof obj === 'undefined';
371
+ }
372
+
373
+ function isDefined(obj) {
374
+ return !isUndefined(obj);
375
+ }
376
+
377
+ function specPluralizedFor(count) {
378
+ var str = count + " spec";
379
+ if (count > 1) {
380
+ str += "s"
381
+ }
382
+ return str;
383
+ }
384
+
385
+ };
386
+
387
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
388
+
389
+
390
+ jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
391
+ this.spec = spec;
392
+ this.dom = dom;
393
+ this.views = views;
394
+
395
+ this.symbol = this.createDom('li', { className: 'pending' });
396
+ this.dom.symbolSummary.appendChild(this.symbol);
397
+
398
+ this.summary = this.createDom('div', { className: 'specSummary' },
399
+ this.createDom('a', {
400
+ className: 'description',
401
+ href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
402
+ title: this.spec.getFullName()
403
+ }, this.spec.description)
404
+ );
405
+
406
+ this.detail = this.createDom('div', { className: 'specDetail' },
407
+ this.createDom('a', {
408
+ className: 'description',
409
+ href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
410
+ title: this.spec.getFullName()
411
+ }, this.spec.getFullName())
412
+ );
413
+ };
414
+
415
+ jasmine.HtmlReporter.SpecView.prototype.status = function() {
416
+ return this.getSpecStatus(this.spec);
417
+ };
418
+
419
+ jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
420
+ this.symbol.className = this.status();
421
+
422
+ switch (this.status()) {
423
+ case 'skipped':
424
+ break;
425
+
426
+ case 'passed':
427
+ this.appendSummaryToSuiteDiv();
428
+ break;
429
+
430
+ case 'failed':
431
+ this.appendSummaryToSuiteDiv();
432
+ this.appendFailureDetail();
433
+ break;
434
+ }
435
+ };
436
+
437
+ jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
438
+ this.summary.className += ' ' + this.status();
439
+ this.appendToSummary(this.spec, this.summary);
440
+ };
441
+
442
+ jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
443
+ this.detail.className += ' ' + this.status();
444
+
445
+ var resultItems = this.spec.results().getItems();
446
+ var messagesDiv = this.createDom('div', { className: 'messages' });
447
+
448
+ for (var i = 0; i < resultItems.length; i++) {
449
+ var result = resultItems[i];
450
+
451
+ if (result.type == 'log') {
452
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
453
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
454
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
455
+
456
+ if (result.trace.stack) {
457
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
458
+ }
459
+ }
460
+ }
461
+
462
+ if (messagesDiv.childNodes.length > 0) {
463
+ this.detail.appendChild(messagesDiv);
464
+ this.dom.details.appendChild(this.detail);
465
+ }
466
+ };
467
+
468
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
469
+ this.suite = suite;
470
+ this.dom = dom;
471
+ this.views = views;
472
+
473
+ this.element = this.createDom('div', { className: 'suite' },
474
+ this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
475
+ );
476
+
477
+ this.appendToSummary(this.suite, this.element);
478
+ };
479
+
480
+ jasmine.HtmlReporter.SuiteView.prototype.status = function() {
481
+ return this.getSpecStatus(this.suite);
482
+ };
483
+
484
+ jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
485
+ this.element.className += " " + this.status();
486
+ };
487
+
488
+ jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
489
+
490
+ /* @deprecated Use jasmine.HtmlReporter instead
491
+ */
492
+ jasmine.TrivialReporter = function(doc) {
493
+ this.document = doc || document;
494
+ this.suiteDivs = {};
495
+ this.logRunningSpecs = false;
496
+ };
497
+
498
+ jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
499
+ var el = document.createElement(type);
500
+
501
+ for (var i = 2; i < arguments.length; i++) {
502
+ var child = arguments[i];
503
+
504
+ if (typeof child === 'string') {
505
+ el.appendChild(document.createTextNode(child));
506
+ } else {
507
+ if (child) { el.appendChild(child); }
508
+ }
509
+ }
510
+
511
+ for (var attr in attrs) {
512
+ if (attr == "className") {
513
+ el[attr] = attrs[attr];
514
+ } else {
515
+ el.setAttribute(attr, attrs[attr]);
516
+ }
517
+ }
518
+
519
+ return el;
520
+ };
521
+
522
+ jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
523
+ var showPassed, showSkipped;
524
+
525
+ this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
526
+ this.createDom('div', { className: 'banner' },
527
+ this.createDom('div', { className: 'logo' },
528
+ this.createDom('span', { className: 'title' }, "Jasmine"),
529
+ this.createDom('span', { className: 'version' }, runner.env.versionString())),
530
+ this.createDom('div', { className: 'options' },
531
+ "Show ",
532
+ showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
533
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
534
+ showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
535
+ this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
536
+ )
537
+ ),
538
+
539
+ this.runnerDiv = this.createDom('div', { className: 'runner running' },
540
+ this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
541
+ this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
542
+ this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
543
+ );
544
+
545
+ this.document.body.appendChild(this.outerDiv);
546
+
547
+ var suites = runner.suites();
548
+ for (var i = 0; i < suites.length; i++) {
549
+ var suite = suites[i];
550
+ var suiteDiv = this.createDom('div', { className: 'suite' },
551
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
552
+ this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
553
+ this.suiteDivs[suite.id] = suiteDiv;
554
+ var parentDiv = this.outerDiv;
555
+ if (suite.parentSuite) {
556
+ parentDiv = this.suiteDivs[suite.parentSuite.id];
557
+ }
558
+ parentDiv.appendChild(suiteDiv);
559
+ }
560
+
561
+ this.startedAt = new Date();
562
+
563
+ var self = this;
564
+ showPassed.onclick = function(evt) {
565
+ if (showPassed.checked) {
566
+ self.outerDiv.className += ' show-passed';
567
+ } else {
568
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
569
+ }
570
+ };
571
+
572
+ showSkipped.onclick = function(evt) {
573
+ if (showSkipped.checked) {
574
+ self.outerDiv.className += ' show-skipped';
575
+ } else {
576
+ self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
577
+ }
578
+ };
579
+ };
580
+
581
+ jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
582
+ var results = runner.results();
583
+ var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
584
+ this.runnerDiv.setAttribute("class", className);
585
+ //do it twice for IE
586
+ this.runnerDiv.setAttribute("className", className);
587
+ var specs = runner.specs();
588
+ var specCount = 0;
589
+ for (var i = 0; i < specs.length; i++) {
590
+ if (this.specFilter(specs[i])) {
591
+ specCount++;
592
+ }
593
+ }
594
+ var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
595
+ message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
596
+ this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
597
+
598
+ this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
599
+ };
600
+
601
+ jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
602
+ var results = suite.results();
603
+ var status = results.passed() ? 'passed' : 'failed';
604
+ if (results.totalCount === 0) { // todo: change this to check results.skipped
605
+ status = 'skipped';
606
+ }
607
+ this.suiteDivs[suite.id].className += " " + status;
608
+ };
609
+
610
+ jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
611
+ if (this.logRunningSpecs) {
612
+ this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
613
+ }
614
+ };
615
+
616
+ jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
617
+ var results = spec.results();
618
+ var status = results.passed() ? 'passed' : 'failed';
619
+ if (results.skipped) {
620
+ status = 'skipped';
621
+ }
622
+ var specDiv = this.createDom('div', { className: 'spec ' + status },
623
+ this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
624
+ this.createDom('a', {
625
+ className: 'description',
626
+ href: '?spec=' + encodeURIComponent(spec.getFullName()),
627
+ title: spec.getFullName()
628
+ }, spec.description));
629
+
630
+
631
+ var resultItems = results.getItems();
632
+ var messagesDiv = this.createDom('div', { className: 'messages' });
633
+ for (var i = 0; i < resultItems.length; i++) {
634
+ var result = resultItems[i];
635
+
636
+ if (result.type == 'log') {
637
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
638
+ } else if (result.type == 'expect' && result.passed && !result.passed()) {
639
+ messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
640
+
641
+ if (result.trace.stack) {
642
+ messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
643
+ }
644
+ }
645
+ }
646
+
647
+ if (messagesDiv.childNodes.length > 0) {
648
+ specDiv.appendChild(messagesDiv);
649
+ }
650
+
651
+ this.suiteDivs[spec.suite.id].appendChild(specDiv);
652
+ };
653
+
654
+ jasmine.TrivialReporter.prototype.log = function() {
655
+ var console = jasmine.getGlobal().console;
656
+ if (console && console.log) {
657
+ if (console.log.apply) {
658
+ console.log.apply(console, arguments);
659
+ } else {
660
+ console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
661
+ }
662
+ }
663
+ };
664
+
665
+ jasmine.TrivialReporter.prototype.getLocation = function() {
666
+ return this.document.location;
667
+ };
668
+
669
+ jasmine.TrivialReporter.prototype.specFilter = function(spec) {
670
+ var paramMap = {};
671
+ var params = this.getLocation().search.substring(1).split('&');
672
+ for (var i = 0; i < params.length; i++) {
673
+ var p = params[i].split('=');
674
+ paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
675
+ }
676
+
677
+ if (!paramMap.spec) {
678
+ return true;
679
+ }
680
+ return spec.getFullName().indexOf(paramMap.spec) === 0;
681
+ };