tdiary 3.2.2.20130617 → 3.2.2.20130720

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,48 +1,46 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'spec_helper'
3
3
 
4
- if defined?(Encoding)
5
- require 'tdiary/compatible'
6
- require 'fileutils'
4
+ require 'tdiary/compatible'
5
+ require 'fileutils'
7
6
 
8
- describe PStore, "auto convert library" do
9
- before do
10
- # rake specで動かすと、comppatible.rb が既に読み込まれてしまっているため、
11
- # このPStoreがASCII-8BITではなくUTF-8になってしまう。
12
- # そのため、下記と同様の ascii8bit-pstore.db をテストフィクスチャとしている。
13
- # PStore.new(@dbfile).transaction do |db|
14
- # db["key1".to_8bit] = "val1".to_8bit
15
- # db["key2".to_8bit] = 2
16
- # db["key3".to_8bit] = [1, :sym, "string".to_8bit]
17
- # end
18
- dbfilename = '../fixtures/ascii8bit-pstore.db'
19
- dbfile_orig = File.join(File.dirname(__FILE__), dbfilename)
20
- @dbfile = File.join(File.dirname(__FILE__), "#{dbfilename}.work")
21
- FileUtils.cp dbfile_orig, @dbfile
22
- end
7
+ describe PStore, "auto convert library" do
8
+ before do
9
+ # rake specで動かすと、comppatible.rb が既に読み込まれてしまっているため、
10
+ # このPStoreがASCII-8BITではなくUTF-8になってしまう。
11
+ # そのため、下記と同様の ascii8bit-pstore.db をテストフィクスチャとしている。
12
+ # PStore.new(@dbfile).transaction do |db|
13
+ # db["key1".to_8bit] = "val1".to_8bit
14
+ # db["key2".to_8bit] = 2
15
+ # db["key3".to_8bit] = [1, :sym, "string".to_8bit]
16
+ # end
17
+ dbfilename = '../fixtures/ascii8bit-pstore.db'
18
+ dbfile_orig = File.join(File.dirname(__FILE__), dbfilename)
19
+ @dbfile = File.join(File.dirname(__FILE__), "#{dbfilename}.work")
20
+ FileUtils.cp dbfile_orig, @dbfile
21
+ end
23
22
 
24
- after do
25
- FileUtils.rm @dbfile
26
- end
23
+ after do
24
+ FileUtils.rm @dbfile
25
+ end
27
26
 
28
- it "should convert an encoding to UTF-8 automatically" do
29
- PStore.new(@dbfile).transaction do |db|
30
- db["key1"].encoding.should == Encoding::UTF_8
31
- db["key2"].should == 2
32
- db["key3"][2].encoding.should == Encoding::UTF_8
33
- end
27
+ it "should convert an encoding to UTF-8 automatically" do
28
+ PStore.new(@dbfile).transaction do |db|
29
+ db["key1"].encoding.should == Encoding::UTF_8
30
+ db["key2"].should == 2
31
+ db["key3"][2].encoding.should == Encoding::UTF_8
34
32
  end
33
+ end
35
34
 
36
- it "1回目のtransactionではMashal.loadが3回呼ばれる" do
37
- Marshal.should_receive(:load).exactly(3).and_return({})
38
- PStore.new(@dbfile).transaction {}
39
- end
35
+ it "1回目のtransactionではMashal.loadが3回呼ばれる" do
36
+ Marshal.should_receive(:load).exactly(3).and_return({})
37
+ PStore.new(@dbfile).transaction {}
38
+ end
40
39
 
41
- it "2回目のtransactionではMashal.loadが1回だけ呼ばれる" do
42
- Marshal.should_receive(:load).exactly(4).and_return({})
43
- PStore.new(@dbfile).transaction {}
44
- PStore.new(@dbfile).transaction {}
45
- end
40
+ it "2回目のtransactionではMashal.loadが1回だけ呼ばれる" do
41
+ Marshal.should_receive(:load).exactly(4).and_return({})
42
+ PStore.new(@dbfile).transaction {}
43
+ PStore.new(@dbfile).transaction {}
46
44
  end
47
45
  end
48
46
 
@@ -2,67 +2,66 @@
2
2
  require 'spec_helper'
3
3
  require 'rack/test'
4
4
  require 'fileutils'
5
+ require 'sprockets'
5
6
  require 'tdiary/rack/assets/precompile'
6
7
 
7
- if defined?(Encoding)
8
- describe TDiary::Rack::Assets::Precompile do
9
- include Rack::Test::Methods
8
+ describe TDiary::Rack::Assets::Precompile do
9
+ include Rack::Test::Methods
10
10
 
11
- let(:app) do
12
- TDiary::Rack::Assets::Precompile.new(lambda{|env| [200, {}, ['Awesome']]}, @environment)
13
- end
14
- let(:assets_path) {"#{TDiary::PATH}/tmp/assets"}
11
+ let(:app) do
12
+ TDiary::Rack::Assets::Precompile.new(lambda{|env| [200, {}, ['Awesome']]}, @environment)
13
+ end
14
+ let(:assets_path) {"#{TDiary::PATH}/tmp/assets"}
15
+
16
+ before do
17
+ FileUtils.mkdir_p assets_path
18
+ @environment = Sprockets::Environment.new
19
+ @environment.append_path assets_path
20
+ end
15
21
 
22
+ after do
23
+ FileUtils.rm_rf assets_path
24
+ end
25
+
26
+ context "JavaScript が無い場合" do
16
27
  before do
17
- FileUtils.mkdir_p assets_path
18
- @environment = Sprockets::Environment.new
19
- @environment.append_path assets_path
28
+ FileUtils.touch "#{assets_path}/foo.coffee"
29
+ get '/'
20
30
  end
21
31
 
22
- after do
23
- FileUtils.rm_rf assets_path
32
+ it "JavaScript にコンパイルされる" do
33
+ FileTest.exist?("#{assets_path}/foo.js").should be_true
24
34
  end
35
+ end
25
36
 
26
- context "JavaScript が無い場合" do
37
+ context "JavaScript がある場合" do
38
+ context "CoffeeScript の方が新しい場合" do
27
39
  before do
40
+ FileUtils.touch "#{assets_path}/foo.js"
41
+ sleep 1
28
42
  FileUtils.touch "#{assets_path}/foo.coffee"
43
+ @jstime = File.mtime("#{assets_path}/foo.js").to_i
44
+
29
45
  get '/'
30
46
  end
31
47
 
32
- it "JavaScript にコンパイルされる" do
33
- FileTest.exist?("#{assets_path}/foo.js").should be_true
48
+ it "JavaScript が更新される" do
49
+ @jstime.should < File.mtime("#{assets_path}/foo.js").to_i
34
50
  end
35
51
  end
36
52
 
37
- context "JavaScript がある場合" do
38
- context "CoffeeScript の方が新しい場合" do
39
- before do
40
- FileUtils.touch "#{assets_path}/foo.js"
41
- sleep 1
42
- FileUtils.touch "#{assets_path}/foo.coffee"
43
- @jstime = File.mtime("#{assets_path}/foo.js").to_i
44
-
45
- get '/'
46
- end
53
+ context "JavaScript の方が新しい場合" do
54
+ before do
55
+ FileUtils.touch "#{assets_path}/foo.coffee"
56
+ sleep 1
57
+ FileUtils.touch "#{assets_path}/foo.js"
58
+ @jstime = File.mtime("#{assets_path}/foo.js").to_i
47
59
 
48
- it "JavaScript が更新される" do
49
- @jstime.should < File.mtime("#{assets_path}/foo.js").to_i
50
- end
60
+ get '/'
51
61
  end
52
62
 
53
- context "JavaScript の方が新しい場合" do
54
- before do
55
- FileUtils.touch "#{assets_path}/foo.coffee"
56
- sleep 1
57
- FileUtils.touch "#{assets_path}/foo.js"
58
- @jstime = File.mtime("#{assets_path}/foo.js").to_i
59
-
60
- get '/'
61
- end
62
-
63
- it "JavaScript は更新されない" do
64
- @jstime.should == File.mtime("#{assets_path}/foo.js").to_i
65
- end
63
+ it "JavaScript は更新されない" do
64
+ @jstime.should == File.mtime("#{assets_path}/foo.js").to_i
66
65
  end
67
66
  end
68
67
  end
@@ -130,6 +130,32 @@ http://www.google.com
130
130
  it { @diary.to_html.should eq @html }
131
131
  end
132
132
 
133
+ describe 'auto imagelink' do
134
+ before do
135
+ source = <<-EOF
136
+ # subTitle
137
+
138
+ ![](http://www.google.com/logo.jpg)
139
+
140
+ ![google](http://www.google.com/logo.jpg)
141
+ EOF
142
+ @diary.append(source)
143
+ @html = <<-EOF
144
+ <div class="section">
145
+ <%=section_enter_proc( Time.at( 1041346800 ) )%>
146
+ <h3><%= subtitle_proc( Time.at( 1041346800 ), "subTitle" ) %></h3>
147
+ <p><img src="http://www.google.com/logo.jpg" alt=""></p>
148
+
149
+ <p><img src="http://www.google.com/logo.jpg" alt="google"></p>
150
+ <%=section_leave_proc( Time.at( 1041346800 ) )%>
151
+ </div>
152
+ EOF
153
+ end
154
+
155
+ it { @diary.to_html.should eq @html }
156
+
157
+ end
158
+
133
159
  describe 'url syntax with code blocks' do
134
160
  before do
135
161
  source = <<-'EOF'
@@ -172,6 +172,28 @@ aaa</p>
172
172
  end
173
173
  end
174
174
 
175
+ describe 'fn' do
176
+ context 'my' do
177
+ before do
178
+ source = <<-'EOF'
179
+ ((-((<20130714>))-))
180
+ EOF
181
+ @diary.append(source)
182
+ end
183
+
184
+ before do
185
+ @html = <<-'EOF'
186
+ <div class="section">
187
+ <%=section_enter_proc( Time::at( 1041346800 ))%>
188
+ <p><%=fn apply_plugin( "<%=my \"20130714\",\"20130714\"%%>" ) %></p>
189
+ <%=section_leave_proc( Time::at( 1041346800 ))%>
190
+ </div>
191
+ EOF
192
+ end
193
+ it { @diary.to_html.should eq @html }
194
+ end
195
+ end
196
+
175
197
  describe 'test_rd_on_error' do
176
198
  context 'link' do
177
199
  before do
@@ -1,3 +1,31 @@
1
+ /*!
2
+ Jasmine-jQuery: a set of jQuery helpers for Jasmine tests.
3
+
4
+ Version 1.5.3
5
+
6
+ https://github.com/velesin/jasmine-jquery
7
+
8
+ Copyright (c) 2010-2013 Wojciech Zawistowski, Travis Jeffery
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining
11
+ a copy of this software and associated documentation files (the
12
+ "Software"), to deal in the Software without restriction, including
13
+ without limitation the rights to use, copy, modify, merge, publish,
14
+ distribute, sublicense, and/or sell copies of the Software, and to
15
+ permit persons to whom the Software is furnished to do so, subject to
16
+ the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be
19
+ included in all copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
+ */
1
29
  var readFixtures = function() {
2
30
  return jasmine.getFixtures().proxyCallTo_('read', arguments)
3
31
  }
@@ -114,27 +142,27 @@ jasmine.Fixtures.prototype.clearCache = function() {
114
142
  }
115
143
 
116
144
  jasmine.Fixtures.prototype.cleanUp = function() {
117
- jQuery('#' + this.containerId).remove()
145
+ $('#' + this.containerId).remove()
118
146
  }
119
147
 
120
148
  jasmine.Fixtures.prototype.sandbox = function(attributes) {
121
149
  var attributesToSet = attributes || {}
122
- return jQuery('<div id="sandbox" />').attr(attributesToSet)
150
+ return $('<div id="sandbox" />').attr(attributesToSet)
123
151
  }
124
152
 
125
153
  jasmine.Fixtures.prototype.createContainer_ = function(html) {
126
154
  var container
127
- if(html instanceof jQuery) {
128
- container = jQuery('<div id="' + this.containerId + '" />')
155
+ if(html instanceof $) {
156
+ container = $('<div id="' + this.containerId + '" />')
129
157
  container.html(html)
130
158
  } else {
131
159
  container = '<div id="' + this.containerId + '">' + html + '</div>'
132
160
  }
133
- jQuery('body').append(container)
161
+ $(document.body).append(container)
134
162
  }
135
163
 
136
164
  jasmine.Fixtures.prototype.addToContainer_ = function(html){
137
- var container = jQuery('body').find('#'+this.containerId).append(html)
165
+ var container = $(document.body).find('#'+this.containerId).append(html)
138
166
  if(!container.length){
139
167
  this.createContainer_(html)
140
168
  }
@@ -149,7 +177,7 @@ jasmine.Fixtures.prototype.getFixtureHtml_ = function(url) {
149
177
 
150
178
  jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
151
179
  var url = this.makeFixtureUrl_(relativeUrl)
152
- var request = jQuery.ajax({
180
+ var request = $.ajax({
153
181
  type: "GET",
154
182
  url: url + "?" + new Date().getTime(),
155
183
  async: false
@@ -201,11 +229,12 @@ jasmine.StyleFixtures.prototype.cleanUp = function() {
201
229
  }
202
230
 
203
231
  jasmine.StyleFixtures.prototype.createStyle_ = function(html) {
204
- var style = jQuery('<style></style>').text(html)
232
+ var styleText = $('<div></div>').html(html).text(),
233
+ style = $('<style>' + styleText + '</style>')
205
234
 
206
235
  this.fixturesNodes_.push(style)
207
236
 
208
- jQuery('head').append(style)
237
+ $('head').append(style)
209
238
  }
210
239
 
211
240
  jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache
@@ -220,8 +249,6 @@ jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.mak
220
249
 
221
250
  jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_
222
251
 
223
- /** jasmine json fixtures */
224
-
225
252
  jasmine.getJSONFixtures = function() {
226
253
  return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
227
254
  }
@@ -248,7 +275,7 @@ jasmine.JSONFixtures.prototype.clearCache = function() {
248
275
  this.fixturesCache_ = {}
249
276
  }
250
277
 
251
- jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {
278
+ jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {
252
279
  this.loadFixtureIntoCache_(url)
253
280
  return this.fixturesCache_[url]
254
281
  }
@@ -256,13 +283,12 @@ jasmine.JSONFixtures.prototype.getFixtureData_ = function(url) {
256
283
  jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function(relativeUrl) {
257
284
  var self = this
258
285
  var url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
259
- jQuery.ajax({
286
+ $.ajax({
260
287
  async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
261
288
  cache: false,
262
289
  dataType: 'json',
263
290
  url: url,
264
291
  success: function(data) {
265
- console.log("Loading data into " + relativeUrl)
266
292
  self.fixturesCache_[relativeUrl] = data
267
293
  },
268
294
  error: function(jqXHR, status, errorThrown) {
@@ -278,13 +304,13 @@ jasmine.JSONFixtures.prototype.proxyCallTo_ = function(methodName, passedArgumen
278
304
  jasmine.JQuery = function() {}
279
305
 
280
306
  jasmine.JQuery.browserTagCaseIndependentHtml = function(html) {
281
- return jQuery('<div/>').append(html).html()
307
+ return $('<div/>').append(html).html()
282
308
  }
283
309
 
284
310
  jasmine.JQuery.elementToString = function(element) {
285
311
  var domEl = $(element).get(0)
286
312
  if (domEl == undefined || domEl.cloneNode)
287
- return jQuery('<div />').append($(element).clone()).html()
313
+ return $('<div />').append($(element).clone()).html()
288
314
  else
289
315
  return element.toString()
290
316
  }
@@ -300,9 +326,9 @@ jasmine.JQuery.matchersClass = {}
300
326
  namespace.events = {
301
327
  spyOn: function(selector, eventName) {
302
328
  var handler = function(e) {
303
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = e
329
+ data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments)
304
330
  }
305
- jQuery(selector).bind(eventName, handler)
331
+ $(selector).on(eventName, handler)
306
332
  data.handlers.push(handler)
307
333
  return {
308
334
  selector: selector,
@@ -314,12 +340,38 @@ jasmine.JQuery.matchersClass = {}
314
340
  }
315
341
  },
316
342
 
343
+ args: function(selector, eventName) {
344
+ var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)];
345
+
346
+ if (!actualArgs) {
347
+ throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent.";
348
+ }
349
+
350
+ return actualArgs;
351
+ },
352
+
317
353
  wasTriggered: function(selector, eventName) {
318
354
  return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
319
355
  },
320
356
 
357
+ wasTriggeredWith: function(selector, eventName, expectedArgs, env) {
358
+ var actualArgs = jasmine.JQuery.events.args(selector, eventName).slice(1);
359
+ if (Object.prototype.toString.call(expectedArgs) !== '[object Array]') {
360
+ actualArgs = actualArgs[0];
361
+ }
362
+ return env.equals_(expectedArgs, actualArgs);
363
+ },
364
+
321
365
  wasPrevented: function(selector, eventName) {
322
- return data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)].isDefaultPrevented()
366
+ var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)],
367
+ e = args ? args[0] : undefined;
368
+ return e && e.isDefaultPrevented()
369
+ },
370
+
371
+ wasStopped: function(selector, eventName) {
372
+ var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)],
373
+ e = args ? args[0] : undefined;
374
+ return e && e.isPropagationStopped()
323
375
  },
324
376
 
325
377
  cleanUp: function() {
@@ -366,6 +418,10 @@ jasmine.JQuery.matchersClass = {}
366
418
  return $(document).find(this.actual).length
367
419
  },
368
420
 
421
+ toHaveLength: function(length) {
422
+ return this.actual.length === length
423
+ },
424
+
369
425
  toHaveAttr: function(attributeName, expectedAttributeValue) {
370
426
  return hasProperty(this.actual.attr(attributeName), expectedAttributeValue)
371
427
  },
@@ -390,15 +446,24 @@ jasmine.JQuery.matchersClass = {}
390
446
 
391
447
  toHaveText: function(text) {
392
448
  var trimmedText = $.trim(this.actual.text())
393
- if (text && jQuery.isFunction(text.test)) {
449
+ if (text && $.isFunction(text.test)) {
394
450
  return text.test(trimmedText)
395
451
  } else {
396
452
  return trimmedText == text
397
453
  }
398
454
  },
399
455
 
456
+ toContainText: function(text) {
457
+ var trimmedText = $.trim(this.actual.text())
458
+ if (text && $.isFunction(text.test)) {
459
+ return text.test(trimmedText)
460
+ } else {
461
+ return trimmedText.indexOf(text) != -1;
462
+ }
463
+ },
464
+
400
465
  toHaveValue: function(value) {
401
- return this.actual.val() == value
466
+ return this.actual.val() === value
402
467
  },
403
468
 
404
469
  toHaveData: function(key, expectedValue) {
@@ -418,7 +483,7 @@ jasmine.JQuery.matchersClass = {}
418
483
  },
419
484
 
420
485
  toBeFocused: function(selector) {
421
- return this.actual.is(':focus')
486
+ return this.actual[0] === this.actual[0].ownerDocument.activeElement
422
487
  },
423
488
 
424
489
  toHandle: function(event) {
@@ -466,7 +531,7 @@ jasmine.JQuery.matchersClass = {}
466
531
 
467
532
  jasmine.JQuery.matchersClass[methodName] = function() {
468
533
  if (this.actual
469
- && (this.actual instanceof jQuery
534
+ && (this.actual instanceof $
470
535
  || jasmine.isDomNode(this.actual))) {
471
536
  this.actual = $(this.actual)
472
537
  var result = jQueryMatchers[methodName].apply(this, arguments)
@@ -515,6 +580,28 @@ beforeEach(function() {
515
580
  return jasmine.JQuery.events.wasTriggered(selector, eventName)
516
581
  }
517
582
  })
583
+ this.addMatchers({
584
+ toHaveBeenTriggeredOnAndWith: function() {
585
+ var selector = arguments[0],
586
+ expectedArgs = arguments[1],
587
+ wasTriggered = jasmine.JQuery.events.wasTriggered(selector, this.actual);
588
+ this.message = function() {
589
+ if (wasTriggered) {
590
+ var actualArgs = jasmine.JQuery.events.args(selector, this.actual, expectedArgs)[1];
591
+ return [
592
+ "Expected event " + this.actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs),
593
+ "Expected event " + this.actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs)
594
+ ]
595
+ } else {
596
+ return [
597
+ "Expected event " + this.actual + " to have been triggered on " + selector,
598
+ "Expected event " + this.actual + " not to have been triggered on " + selector
599
+ ]
600
+ }
601
+ }
602
+ return wasTriggered && jasmine.JQuery.events.wasTriggeredWith(selector, this.actual, expectedArgs, this.env);
603
+ }
604
+ })
518
605
  this.addMatchers({
519
606
  toHaveBeenPreventedOn: function(selector) {
520
607
  this.message = function() {
@@ -539,6 +626,30 @@ beforeEach(function() {
539
626
  return jasmine.JQuery.events.wasPrevented(selector, eventName)
540
627
  }
541
628
  })
629
+ this.addMatchers({
630
+ toHaveBeenStoppedOn: function(selector) {
631
+ this.message = function() {
632
+ return [
633
+ "Expected event " + this.actual + " to have been stopped on " + selector,
634
+ "Expected event " + this.actual + " not to have been stopped on " + selector
635
+ ]
636
+ }
637
+ return jasmine.JQuery.events.wasStopped(selector, this.actual)
638
+ }
639
+ })
640
+ this.addMatchers({
641
+ toHaveBeenStopped: function() {
642
+ var eventName = this.actual.eventName,
643
+ selector = this.actual.selector
644
+ this.message = function() {
645
+ return [
646
+ "Expected event " + eventName + " to have been stopped on " + selector,
647
+ "Expected event " + eventName + " not to have been stopped on " + selector
648
+ ]
649
+ }
650
+ return jasmine.JQuery.events.wasStopped(selector, eventName)
651
+ }
652
+ })
542
653
  })
543
654
 
544
655
  afterEach(function() {