jspec 3.3.3 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.md +22 -0
- data/README.md +85 -26
- data/bin/jspec +1 -1
- data/jspec.gemspec +2 -2
- data/lib/jspec.js +188 -68
- data/spec/node.js +1 -1
- data/spec/unit/spec.fixtures.js +7 -0
- data/spec/unit/spec.grammar.js +65 -31
- data/spec/unit/spec.shared-behaviors.js +246 -47
- metadata +5 -5
data/History.md
CHANGED
@@ -1,4 +1,26 @@
|
|
1
1
|
|
2
|
+
4.0.0 / 2010-03-22
|
3
|
+
==================
|
4
|
+
|
5
|
+
* Added json_fixture(). Closes #157
|
6
|
+
|
7
|
+
* Added swalke16 to contrib list (shared behavior fixes)
|
8
|
+
|
9
|
+
* Added shared_behaviors_for() for shared behavior support.
|
10
|
+
This is essentially a Suite instance, however the shared
|
11
|
+
behavior itself is no longer executed, only suites which use
|
12
|
+
should_behave_like().
|
13
|
+
|
14
|
+
* Added before_nested / after_nested for legacy support.
|
15
|
+
These hooks function just as before / after did < 4.0.0,
|
16
|
+
where they will execute once per nested suite as well.
|
17
|
+
|
18
|
+
* Changed; before / after are now executed ONLY once, not
|
19
|
+
when a nested suite is running. Use before_nested / after_nested
|
20
|
+
if you wish to re-gain this functionality.
|
21
|
+
|
22
|
+
* Removed JSpec.error()
|
23
|
+
|
2
24
|
3.3.3 / 2010-03-15
|
3
25
|
==================
|
4
26
|
|
data/README.md
CHANGED
@@ -48,6 +48,7 @@ To add or request removal from this list please email tj@vision-media.ca
|
|
48
48
|
* [Google - YouTube](http://youtube.com)
|
49
49
|
* [Palm](http://palm.com)
|
50
50
|
* [Carfax](http://carfax.com)
|
51
|
+
* [Apache CouchDB](http://couchdb.apache.org)
|
51
52
|
* [Vision Media](http://vision-media.ca)
|
52
53
|
|
53
54
|
## Installation
|
@@ -364,34 +365,81 @@ on any object when using the JSpec grammar:
|
|
364
365
|
## Shared Behaviors
|
365
366
|
|
366
367
|
JSpec's support for shared behaviors allows multiple suites or describe blocks to share
|
367
|
-
common functionality
|
368
|
+
common functionality, including specs and hooks. Shared functionality is run in the order in
|
369
|
+
which it is included in the hosting suite. For example a canine would inherit all
|
370
|
+
behavior of an animal, and particular breeds of dog would inherit all behavior from the canine.
|
371
|
+
Note that as in the poodle example, shared behaviors can be nested inside suites or describe
|
372
|
+
blocks and will be visible only to other describe blocks _at or below_ the same nesting level.
|
373
|
+
|
374
|
+
shared_behaviors_for 'animal'
|
375
|
+
before
|
376
|
+
animal = { eats: function(){return true }}
|
377
|
+
end
|
378
|
+
|
379
|
+
it 'should eat'
|
380
|
+
animal.eats().should.eql true
|
381
|
+
end
|
382
|
+
end
|
383
|
+
|
384
|
+
shared_behaviors_for 'canine'
|
385
|
+
should_behave_like('animal')
|
386
|
+
|
387
|
+
before
|
388
|
+
animal.hasFourLegs = function(){ return true }
|
389
|
+
animal.barks = function(){ return true }
|
390
|
+
end
|
391
|
+
|
392
|
+
it 'should have 4 legs'
|
393
|
+
animal.hasFourLegs().should.eql true
|
394
|
+
end
|
395
|
+
|
396
|
+
it 'should bark'
|
397
|
+
animal.barks().should.eql true
|
398
|
+
end
|
399
|
+
end
|
368
400
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
it 'should have a name'
|
376
|
-
user.should.have_property 'name'
|
377
|
-
end
|
378
|
-
|
379
|
-
describe 'Administrator'
|
380
|
-
should_behave_like('User')
|
381
|
-
|
382
|
-
before
|
383
|
-
Admin = function(name) { this.name = name }
|
384
|
-
Admin.prototype.may = function(perm){ return true }
|
385
|
-
user = new Admin('tj')
|
386
|
-
end
|
387
|
-
|
388
|
-
it 'should have access to all permissions'
|
389
|
-
user.may('edit pages').should.be_true
|
390
|
-
end
|
391
|
-
end
|
392
|
-
end
|
401
|
+
describe 'mastif'
|
402
|
+
should_behave_like('canine')
|
403
|
+
|
404
|
+
before
|
405
|
+
animal.weight = 200
|
406
|
+
end
|
393
407
|
|
394
|
-
|
408
|
+
it 'should weigh > 100 lbs'
|
409
|
+
animal.weight.should.be_greater_than 100
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
describe 'poodle breeds'
|
414
|
+
should_behave_like('canine')
|
415
|
+
|
416
|
+
shared_behaviors_for 'poodle'
|
417
|
+
before
|
418
|
+
animal.isMean = true
|
419
|
+
end
|
420
|
+
|
421
|
+
it 'should be mean'
|
422
|
+
animal.isMean.should.eql true
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
describe 'fancy poodle'
|
427
|
+
should_behave_like('poodle')
|
428
|
+
|
429
|
+
before
|
430
|
+
animal.looksRidiculous = true
|
431
|
+
end
|
432
|
+
|
433
|
+
it 'should look ridiculous'
|
434
|
+
animal.looksRidiculous.should.eql true
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
NOTE: When the should_behave_like() call is searching for behaviors to include, it works inside out.
|
440
|
+
Therefore any nested shared behaviors by the same name as a shared behavior at a higher
|
441
|
+
nesting level will override the one at the higher level.
|
442
|
+
|
395
443
|
|
396
444
|
## Mock Ajax Requests
|
397
445
|
|
@@ -430,6 +478,10 @@ scope, they will both run, but this can help keep your specs readable.
|
|
430
478
|
- run before each specification
|
431
479
|
- after_each
|
432
480
|
- run after each specification
|
481
|
+
- before_nested
|
482
|
+
- run once before the suite and once before any nested suites
|
483
|
+
- after_nested
|
484
|
+
- run once after the suite and once after any nested suites
|
433
485
|
|
434
486
|
## Custom Contexts
|
435
487
|
|
@@ -540,6 +592,12 @@ manor:
|
|
540
592
|
In order for the `fixture()` utility to function you must pass the **fixturePath** option
|
541
593
|
to _JSpec.run()_ which provides JSpec with the fixture directory.
|
542
594
|
|
595
|
+
The `json_fixture()` utility works much the same as `fixture()` however `fixture('data')`
|
596
|
+
will be parsed as JSON, and resolved as shown below:
|
597
|
+
|
598
|
+
- <fixturePath>/data
|
599
|
+
- <fixturePath>/data.json
|
600
|
+
|
543
601
|
## Testing DOM Elements
|
544
602
|
|
545
603
|
When using jQuery testing DOM elements is very easy. Many may think they require specific
|
@@ -940,6 +998,7 @@ missed you on this list please let me know
|
|
940
998
|
- [kevin.gisi@gmail.com](kevin.gisi@gmail.com)
|
941
999
|
- [tony_t_tubbs@yahoo.com](tony_t_tubbs@yahoo.com)
|
942
1000
|
- [enno84@gmx.net](enno84@gmx.net)
|
1001
|
+
- swalke16
|
943
1002
|
- fnando
|
944
1003
|
- Tobias Svensson
|
945
1004
|
|
data/bin/jspec
CHANGED
data/jspec.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{jspec}
|
5
|
-
s.version = "
|
5
|
+
s.version = "4.0.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["TJ Holowaychuk"]
|
9
|
-
s.date = %q{2010-03-
|
9
|
+
s.date = %q{2010-03-22}
|
10
10
|
s.default_executable = %q{jspec}
|
11
11
|
s.description = %q{JavaScript BDD Testing Framework}
|
12
12
|
s.email = %q{tj@vision-media.ca}
|
data/lib/jspec.js
CHANGED
@@ -4,12 +4,13 @@
|
|
4
4
|
;(function(){
|
5
5
|
|
6
6
|
JSpec = {
|
7
|
-
version : '
|
7
|
+
version : '4.0.0',
|
8
8
|
assert : true,
|
9
9
|
cache : {},
|
10
10
|
suites : [],
|
11
11
|
modules : [],
|
12
12
|
allSuites : [],
|
13
|
+
sharedBehaviors: [],
|
13
14
|
matchers : {},
|
14
15
|
stubbed : [],
|
15
16
|
options : {},
|
@@ -68,6 +69,31 @@
|
|
68
69
|
return JSpec.cache[path] =
|
69
70
|
JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) ||
|
70
71
|
JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.html')
|
72
|
+
},
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Load json fixture at _path_.
|
76
|
+
*
|
77
|
+
* JSON fixtures are resolved as:
|
78
|
+
*
|
79
|
+
* - <path>
|
80
|
+
* - <path>.json
|
81
|
+
*
|
82
|
+
* @param {string} path
|
83
|
+
* @return {object}
|
84
|
+
* @api public
|
85
|
+
*/
|
86
|
+
|
87
|
+
json_fixture: function(path) {
|
88
|
+
if (!JSpec.cache['json:' + path])
|
89
|
+
JSpec.cache['json:' + path] =
|
90
|
+
JSpec.tryLoading(JSpec.options.fixturePath + '/' + path) ||
|
91
|
+
JSpec.tryLoading(JSpec.options.fixturePath + '/' + path + '.json')
|
92
|
+
try {
|
93
|
+
return eval('(' + JSpec.cache['json:' + path] + ')')
|
94
|
+
} catch (e) {
|
95
|
+
throw 'json_fixture("' + path + '"): ' + e
|
96
|
+
}
|
71
97
|
}
|
72
98
|
},
|
73
99
|
|
@@ -92,7 +118,7 @@
|
|
92
118
|
stats: JSpec.stats,
|
93
119
|
options: options,
|
94
120
|
results: map(results.allSuites, function(suite) {
|
95
|
-
if (suite.
|
121
|
+
if (suite.isExecutable())
|
96
122
|
return {
|
97
123
|
description: suite.description,
|
98
124
|
specs: map(suite.specs, function(spec) {
|
@@ -145,7 +171,7 @@
|
|
145
171
|
<span class="passes">Duration: <em>' + results.duration + '</em> ms</span> \
|
146
172
|
</div><table class="suites">' + map(results.allSuites, function(suite) {
|
147
173
|
var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran
|
148
|
-
if (displaySuite && suite.
|
174
|
+
if (displaySuite && suite.isExecutable())
|
149
175
|
return '<tr class="description"><td colspan="2">' + escape(suite.description) + '</td></tr>' +
|
150
176
|
map(suite.specs, function(i, spec) {
|
151
177
|
return '<tr class="' + (i % 2 ? 'odd' : 'even') + '">' +
|
@@ -181,7 +207,7 @@
|
|
181
207
|
|
182
208
|
each(results.allSuites, function(suite) {
|
183
209
|
var displaySuite = failuresOnly ? suite.ran && !suite.passed() : suite.ran
|
184
|
-
if (displaySuite && suite.
|
210
|
+
if (displaySuite && suite.isExecutable()) {
|
185
211
|
print(color(' ' + suite.description, 'bold'))
|
186
212
|
each(suite.specs, function(spec){
|
187
213
|
var assertionsGraph = inject(spec.assertions, '', function(graph, assertion){
|
@@ -392,17 +418,21 @@
|
|
392
418
|
* @api private
|
393
419
|
*/
|
394
420
|
|
395
|
-
Suite : function(description, body) {
|
421
|
+
Suite : function(description, body, isShared) {
|
396
422
|
var self = this
|
397
423
|
extend(this, {
|
398
424
|
body: body,
|
399
425
|
description: description,
|
400
426
|
suites: [],
|
427
|
+
sharedBehaviors: [],
|
401
428
|
specs: [],
|
402
429
|
ran: false,
|
403
|
-
|
430
|
+
shared: isShared,
|
431
|
+
hooks: { 'before' : [], 'after' : [],
|
432
|
+
'before_each' : [], 'after_each' : [],
|
433
|
+
'before_nested' : [], 'after_nested' : []},
|
404
434
|
|
405
|
-
|
435
|
+
// Add a spec to the suite
|
406
436
|
|
407
437
|
addSpec : function(description, body) {
|
408
438
|
var spec = new JSpec.Spec(description, body)
|
@@ -411,16 +441,30 @@
|
|
411
441
|
spec.suite = this
|
412
442
|
},
|
413
443
|
|
414
|
-
// Add a hook to the suite
|
444
|
+
// Add a before hook to the suite
|
445
|
+
|
446
|
+
addBefore : function(options, body) {
|
447
|
+
body.options = options || {}
|
448
|
+
this.befores.push(body)
|
449
|
+
},
|
415
450
|
|
451
|
+
// Add an after hook to the suite
|
452
|
+
|
453
|
+
addAfter : function(options, body) {
|
454
|
+
body.options = options || {}
|
455
|
+
this.afters.unshift(body)
|
456
|
+
},
|
457
|
+
|
458
|
+
// Add a hook to the suite
|
459
|
+
|
416
460
|
addHook : function(hook, body) {
|
417
461
|
this.hooks[hook].push(body)
|
418
462
|
},
|
419
463
|
|
420
464
|
// Add a nested suite
|
421
465
|
|
422
|
-
addSuite : function(description, body) {
|
423
|
-
var suite = new JSpec.Suite(description, body)
|
466
|
+
addSuite : function(description, body, isShared) {
|
467
|
+
var suite = new JSpec.Suite(description, body, isShared)
|
424
468
|
JSpec.allSuites.push(suite)
|
425
469
|
suite.name = suite.description
|
426
470
|
suite.description = this.description + ' ' + suite.description
|
@@ -428,15 +472,17 @@
|
|
428
472
|
suite.suite = this
|
429
473
|
},
|
430
474
|
|
431
|
-
|
475
|
+
// Invoke a hook in context to this suite
|
432
476
|
|
433
477
|
hook : function(hook) {
|
434
|
-
|
478
|
+
if (hook != 'before' && hook != 'after')
|
479
|
+
if (this.suite) this.suite.hook(hook)
|
480
|
+
|
435
481
|
each(this.hooks[hook], function(body) {
|
436
482
|
JSpec.evalBody(body, "Error in hook '" + hook + "', suite '" + self.description + "': ")
|
437
483
|
})
|
438
484
|
},
|
439
|
-
|
485
|
+
|
440
486
|
// Check if nested suites are present
|
441
487
|
|
442
488
|
hasSuites : function() {
|
@@ -455,7 +501,15 @@
|
|
455
501
|
return !any(this.specs, function(spec){
|
456
502
|
return !spec.passed()
|
457
503
|
})
|
458
|
-
}
|
504
|
+
},
|
505
|
+
|
506
|
+
isShared : function(){
|
507
|
+
return this.shared
|
508
|
+
},
|
509
|
+
|
510
|
+
isExecutable : function() {
|
511
|
+
return !this.isShared() && this.hasSpecs()
|
512
|
+
}
|
459
513
|
})
|
460
514
|
},
|
461
515
|
|
@@ -603,7 +657,7 @@
|
|
603
657
|
},
|
604
658
|
|
605
659
|
describe : function(description, body) {
|
606
|
-
return JSpec.currentSuite.addSuite(description, body)
|
660
|
+
return JSpec.currentSuite.addSuite(description, body, false)
|
607
661
|
},
|
608
662
|
|
609
663
|
it : function(description, body) {
|
@@ -613,19 +667,31 @@
|
|
613
667
|
before : function(body) {
|
614
668
|
return JSpec.currentSuite.addHook('before', body)
|
615
669
|
},
|
616
|
-
|
670
|
+
|
617
671
|
after : function(body) {
|
618
672
|
return JSpec.currentSuite.addHook('after', body)
|
619
673
|
},
|
620
|
-
|
674
|
+
|
621
675
|
before_each : function(body) {
|
622
676
|
return JSpec.currentSuite.addHook('before_each', body)
|
623
677
|
},
|
624
|
-
|
678
|
+
|
625
679
|
after_each : function(body) {
|
626
680
|
return JSpec.currentSuite.addHook('after_each', body)
|
627
681
|
},
|
682
|
+
|
683
|
+
before_nested : function(body) {
|
684
|
+
return JSpec.currentSuite.addHook('before_nested', body)
|
685
|
+
},
|
686
|
+
|
687
|
+
after_nested : function(body){
|
688
|
+
return JSpec.currentSuite.addhook('after_nested', body)
|
689
|
+
},
|
628
690
|
|
691
|
+
shared_behaviors_for : function(description, body){
|
692
|
+
return JSpec.currentSuite.addSuite(description, body, true)
|
693
|
+
},
|
694
|
+
|
629
695
|
should_behave_like : function(description) {
|
630
696
|
return JSpec.shareBehaviorsOf(description)
|
631
697
|
}
|
@@ -702,8 +768,7 @@
|
|
702
768
|
|
703
769
|
evalHook : function(module, name, args) {
|
704
770
|
hook('evaluatingHookBody', module, name)
|
705
|
-
|
706
|
-
catch(e) { error('Error in hook ' + module.name + '.' + name + ': ', e) }
|
771
|
+
return module[name].apply(module, args)
|
707
772
|
},
|
708
773
|
|
709
774
|
/**
|
@@ -726,19 +791,69 @@
|
|
726
791
|
},
|
727
792
|
|
728
793
|
/**
|
729
|
-
* Find a suite by its description or name.
|
794
|
+
* Find a shared example suite by its description or name.
|
795
|
+
* First searches parent tree of suites for shared behavior
|
796
|
+
* before falling back to global scoped nested behaviors.
|
730
797
|
*
|
731
798
|
* @param {string} description
|
732
799
|
* @return {Suite}
|
733
800
|
* @api private
|
734
801
|
*/
|
735
802
|
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
803
|
+
findSharedBehavior : function(description) {
|
804
|
+
var behavior
|
805
|
+
return (behavior = JSpec.findLocalSharedBehavior(description))
|
806
|
+
? behavior
|
807
|
+
: JSpec.findGlobalSharedBehavior(description)
|
740
808
|
},
|
809
|
+
|
810
|
+
/**
|
811
|
+
* Find a shared example suite within the current suite's
|
812
|
+
* parent tree by its description or name.
|
813
|
+
*
|
814
|
+
* @param {string} description
|
815
|
+
* @return {Suite}
|
816
|
+
* @api private
|
817
|
+
*/
|
818
|
+
|
819
|
+
findLocalSharedBehavior : function(description) {
|
820
|
+
var behavior,
|
821
|
+
currentSuite = JSpec.currentSuite.suite
|
822
|
+
while (currentSuite)
|
823
|
+
if (behavior = find(currentSuite.suites, JSpec.suiteDescriptionPredicate(description)))
|
824
|
+
return behavior
|
825
|
+
else
|
826
|
+
currentSuite = currentSuite.suite
|
827
|
+
},
|
828
|
+
|
829
|
+
/**
|
830
|
+
* Find a shared example suite within the global
|
831
|
+
* scope by its description or name.
|
832
|
+
*
|
833
|
+
* @param {string} description
|
834
|
+
* @return {Suite}
|
835
|
+
* @api private
|
836
|
+
*/
|
837
|
+
|
838
|
+
findGlobalSharedBehavior : function(description) {
|
839
|
+
return find(JSpec.suites, JSpec.suiteDescriptionPredicate(description))
|
840
|
+
},
|
741
841
|
|
842
|
+
/**
|
843
|
+
* Build a predicate that will match a suite based on name or description
|
844
|
+
*
|
845
|
+
* @param {string} description
|
846
|
+
* @return {function}
|
847
|
+
* @api private
|
848
|
+
*/
|
849
|
+
|
850
|
+
suiteDescriptionPredicate : function(description) {
|
851
|
+
return function(suite){
|
852
|
+
return suite.name === description ||
|
853
|
+
suite.description === description
|
854
|
+
}
|
855
|
+
},
|
856
|
+
|
742
857
|
/**
|
743
858
|
* Share behaviors (specs) of the given suite with
|
744
859
|
* the current suite.
|
@@ -748,26 +863,13 @@
|
|
748
863
|
*/
|
749
864
|
|
750
865
|
shareBehaviorsOf : function(description) {
|
751
|
-
|
752
|
-
|
866
|
+
var suite = JSpec.findSharedBehavior(description)
|
867
|
+
if (suite)
|
868
|
+
JSpec.evalBody(suite.body)
|
869
|
+
else
|
870
|
+
throw new Error("failed to find shared behaviors named `" + description + "'")
|
753
871
|
},
|
754
872
|
|
755
|
-
/**
|
756
|
-
* Copy specs from one suite to another.
|
757
|
-
*
|
758
|
-
* @param {Suite} fromSuite
|
759
|
-
* @param {Suite} toSuite
|
760
|
-
* @api public
|
761
|
-
*/
|
762
|
-
|
763
|
-
copySpecs : function(fromSuite, toSuite) {
|
764
|
-
each(fromSuite.specs, function(spec){
|
765
|
-
var newSpec = new Object();
|
766
|
-
extend(newSpec, spec);
|
767
|
-
newSpec.assertions = [];
|
768
|
-
toSuite.specs.push(newSpec);
|
769
|
-
})
|
770
|
-
},
|
771
873
|
|
772
874
|
/**
|
773
875
|
* Convert arguments to an array.
|
@@ -1277,12 +1379,27 @@
|
|
1277
1379
|
*/
|
1278
1380
|
|
1279
1381
|
describe : function(description, body) {
|
1280
|
-
var suite = new JSpec.Suite(description, body)
|
1382
|
+
var suite = new JSpec.Suite(description, body, false)
|
1281
1383
|
hook('addingSuite', suite)
|
1282
1384
|
this.allSuites.push(suite)
|
1283
1385
|
this.suites.push(suite)
|
1284
1386
|
},
|
1285
1387
|
|
1388
|
+
/**
|
1389
|
+
* Add a shared example suite to JSpec.
|
1390
|
+
*
|
1391
|
+
* @param {string} description
|
1392
|
+
* @param {body} function
|
1393
|
+
* @api public
|
1394
|
+
*/
|
1395
|
+
|
1396
|
+
shared_behaviors_for : function(description, body) {
|
1397
|
+
var suite = new JSpec.Suite(description, body, true)
|
1398
|
+
hook('addingSuite', suite)
|
1399
|
+
this.allSuites.push(suite)
|
1400
|
+
this.suites.push(suite)
|
1401
|
+
},
|
1402
|
+
|
1286
1403
|
/**
|
1287
1404
|
* Return the contents of a function body.
|
1288
1405
|
*
|
@@ -1309,9 +1426,8 @@
|
|
1309
1426
|
var matchers = this.matchers
|
1310
1427
|
var context = this.context || this.defaultContext
|
1311
1428
|
var contents = this.contentsOf(body)
|
1312
|
-
|
1313
|
-
|
1314
|
-
catch(e) { error(errorMessage, e) }
|
1429
|
+
hook('evaluatingBody', dsl, matchers, context, contents)
|
1430
|
+
with (dsl){ with (context) { with (matchers) { eval(contents) }}}
|
1315
1431
|
},
|
1316
1432
|
|
1317
1433
|
/**
|
@@ -1331,8 +1447,9 @@
|
|
1331
1447
|
split('__END__')[0].
|
1332
1448
|
replace(/([\w\.]+)\.(stub|destub)\((.*?)\)$/gm, '$2($1, $3)').
|
1333
1449
|
replace(/describe\s+(.*?)$/gm, 'describe($1, function(){').
|
1450
|
+
replace(/shared_behaviors_for\s+(.*?)$/gm, 'shared_behaviors_for($1, function(){').
|
1334
1451
|
replace(/^\s+it\s+(.*?)$/gm, ' it($1, function(){').
|
1335
|
-
|
1452
|
+
replace(/^ *(before_nested|after_nested|before_each|after_each|before|after)(?= |\n|$)/gm, 'JSpec.currentSuite.addHook("$1", function(){').
|
1336
1453
|
replace(/^\s*end(?=\s|$)/gm, '});').
|
1337
1454
|
replace(/-\{/g, 'function(){').
|
1338
1455
|
replace(/(\d+)\.\.(\d+)/g, function(_, a, b){ return range(a, b) }).
|
@@ -1395,25 +1512,28 @@
|
|
1395
1512
|
*/
|
1396
1513
|
|
1397
1514
|
runSuite : function(suite) {
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1405
|
-
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1515
|
+
if (!suite.isShared())
|
1516
|
+
{
|
1517
|
+
this.currentSuite = suite
|
1518
|
+
this.evalBody(suite.body)
|
1519
|
+
suite.ran = true
|
1520
|
+
hook('beforeSuite', suite), suite.hook('before'), suite.hook('before_nested')
|
1521
|
+
each(suite.specs, function(spec) {
|
1522
|
+
hook('beforeSpec', spec)
|
1523
|
+
suite.hook('before_each')
|
1524
|
+
JSpec.runSpec(spec)
|
1525
|
+
hook('afterSpec', spec)
|
1526
|
+
suite.hook('after_each')
|
1527
|
+
})
|
1528
|
+
if (suite.hasSuites()) {
|
1529
|
+
each(suite.suites, function(suite) {
|
1530
|
+
JSpec.runSuite(suite)
|
1531
|
+
})
|
1532
|
+
}
|
1533
|
+
hook('afterSuite', suite), suite.hook('after_nested'), suite.hook('after')
|
1534
|
+
this.stats.suitesFinished++
|
1535
|
+
}
|
1536
|
+
},
|
1417
1537
|
|
1418
1538
|
/**
|
1419
1539
|
* Report a failure for the current spec.
|
@@ -1596,7 +1716,7 @@
|
|
1596
1716
|
return request.responseText
|
1597
1717
|
}
|
1598
1718
|
else
|
1599
|
-
|
1719
|
+
throw new Error("failed to load `" + file + "'")
|
1600
1720
|
},
|
1601
1721
|
|
1602
1722
|
/**
|
data/spec/node.js
CHANGED
@@ -12,6 +12,6 @@ JSpec
|
|
12
12
|
.exec('spec/unit/spec.shared-behaviors.js')
|
13
13
|
.exec('spec/unit/spec.grammar.js')
|
14
14
|
.exec('spec/unit/spec.grammar-less.js')
|
15
|
-
|
15
|
+
.exec('spec/unit/spec.fixtures.js')
|
16
16
|
.run({ reporter: JSpec.reporters.Terminal, failuresOnly: true, fixturePath: 'spec/fixtures' })
|
17
17
|
.report()
|
data/spec/unit/spec.fixtures.js
CHANGED
@@ -14,4 +14,11 @@ describe 'Utility'
|
|
14
14
|
delete JSpec.cache['test']
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
describe 'json_fixture()'
|
19
|
+
it 'should evaluate json fixtures'
|
20
|
+
json_fixture('test').should.eql { users : { tj : { email : 'tj@vision-media.ca' }}}
|
21
|
+
json_fixture('test.json').should.eql { users : { tj : { email : 'tj@vision-media.ca' }}}
|
22
|
+
end
|
23
|
+
end
|
17
24
|
end
|
data/spec/unit/spec.grammar.js
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
|
2
1
|
describe 'Grammar'
|
3
|
-
|
4
|
-
it 'should allow "it" spec literal'
|
2
|
+
it 'should allow "it" spec literal'
|
5
3
|
true.should.be_true
|
6
4
|
end
|
7
5
|
|
@@ -10,7 +8,7 @@ describe 'Grammar'
|
|
10
8
|
it 'should allow literal javascript outside of blocks'
|
11
9
|
n.should.eql 10
|
12
10
|
end
|
13
|
-
|
11
|
+
|
14
12
|
it 'should escape <html> in <p>descriptions</p> and body'
|
15
13
|
'<p></p>'.should.eql '<p></p>'
|
16
14
|
end
|
@@ -75,9 +73,9 @@ describe 'Grammar'
|
|
75
73
|
|
76
74
|
it 'should allow multi-line expect() assertions'
|
77
75
|
expect(' \
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
foo \
|
77
|
+
bar \
|
78
|
+
').to(include, 'foo', 'bar')
|
81
79
|
end
|
82
80
|
|
83
81
|
it 'should allow commenting out of conversions'
|
@@ -106,21 +104,21 @@ describe 'Grammar'
|
|
106
104
|
'bar'.should.not.equal 'foo'
|
107
105
|
end
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
107
|
+
describe 'with tabs'
|
108
|
+
before_each
|
109
|
+
foo = 'bar'
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should work'
|
113
|
+
foo.should.eql 'bar'
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should work'
|
117
|
+
true.should.be true
|
118
|
+
true.should.be(true)
|
119
|
+
true.should.be(true);
|
120
|
+
end
|
121
|
+
end
|
124
122
|
|
125
123
|
describe 'with nested describe'
|
126
124
|
it 'should work'
|
@@ -141,7 +139,7 @@ describe 'Grammar'
|
|
141
139
|
hits.push('before')
|
142
140
|
end
|
143
141
|
|
144
|
-
after
|
142
|
+
after
|
145
143
|
n = 0
|
146
144
|
hits.push('after')
|
147
145
|
end
|
@@ -158,15 +156,51 @@ describe 'Grammar'
|
|
158
156
|
end
|
159
157
|
|
160
158
|
describe 'with nested describe'
|
161
|
-
it 'should be accessable'
|
162
|
-
n.should.eql
|
163
|
-
hits.should.eql ['before']
|
159
|
+
it 'variables should be accessable'
|
160
|
+
n.should.eql 2
|
164
161
|
end
|
162
|
+
|
163
|
+
it 'should only run for outer describe'
|
164
|
+
hits.should.eql ['before']
|
165
|
+
end
|
165
166
|
end
|
166
167
|
end
|
167
168
|
|
169
|
+
describe 'before_nested / after_nested blocks'
|
170
|
+
before
|
171
|
+
x = 0
|
172
|
+
y = 0
|
173
|
+
end
|
174
|
+
|
175
|
+
before_nested
|
176
|
+
x++
|
177
|
+
end
|
178
|
+
|
179
|
+
after_nested
|
180
|
+
y++
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'should execute before_nested before suite'
|
184
|
+
x.should.eql 1
|
185
|
+
end
|
186
|
+
|
187
|
+
describe 'with nested describe'
|
188
|
+
it 'should execute before_nested before nested suite'
|
189
|
+
x.should.eql 2
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'after_nested'
|
194
|
+
it 'should execute after_nested after nested suite'
|
195
|
+
y.should.eql 1
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
168
200
|
describe 'before_each / after_each blocks'
|
169
|
-
|
201
|
+
before
|
202
|
+
hits = []
|
203
|
+
end
|
170
204
|
|
171
205
|
before_each
|
172
206
|
n = 1
|
@@ -202,7 +236,7 @@ describe 'Grammar'
|
|
202
236
|
end
|
203
237
|
|
204
238
|
describe 'with more hooks'
|
205
|
-
before_each
|
239
|
+
before_each
|
206
240
|
hits.push('before_each')
|
207
241
|
end
|
208
242
|
|
@@ -232,10 +266,10 @@ describe 'Grammar'
|
|
232
266
|
end
|
233
267
|
|
234
268
|
end
|
235
|
-
|
269
|
+
|
236
270
|
__END__
|
237
|
-
|
271
|
+
|
238
272
|
this should not matter because it is
|
239
273
|
considered a comment by the JSpec grammar :)
|
240
|
-
and is sometimes useful for temp reference info
|
274
|
+
and is sometimes useful for temp reference info
|
241
275
|
when writting specs.
|
@@ -1,80 +1,279 @@
|
|
1
|
+
shared_behaviors_for 'animal'
|
2
|
+
before
|
3
|
+
animal = { eats: function(){ return true } }
|
4
|
+
end
|
5
|
+
|
6
|
+
it 'should eat'
|
7
|
+
animal.eats().should.eql true
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
shared_behaviors_for 'canine'
|
12
|
+
should_behave_like('animal')
|
13
|
+
|
14
|
+
before
|
15
|
+
animal.hasFourLegs = function(){ return true }
|
16
|
+
animal.barks = function(){ return true }
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have 4 legs'
|
20
|
+
animal.hasFourLegs().should.eql true
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should bark'
|
24
|
+
animal.barks().should.eql true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'mastif'
|
29
|
+
should_behave_like('canine')
|
30
|
+
|
31
|
+
before
|
32
|
+
animal.weight = 200
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should weigh > 100 lbs'
|
36
|
+
animal.weight.should.be_greater_than 100
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'poodle breeds'
|
41
|
+
should_behave_like('canine')
|
42
|
+
|
43
|
+
shared_behaviors_for 'poodle'
|
44
|
+
before
|
45
|
+
animal.isMean = true
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should be mean'
|
49
|
+
animal.isMean.should.eql true
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe 'fancy poodle'
|
54
|
+
should_behave_like('poodle')
|
55
|
+
|
56
|
+
before
|
57
|
+
animal.looksRidiculous = true
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should look ridiculous'
|
61
|
+
animal.looksRidiculous.should.eql true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'shared behaviors'
|
67
|
+
before
|
68
|
+
before_sequence = []
|
69
|
+
before_each_sequence = []
|
70
|
+
after_sequence = []
|
71
|
+
after_each_sequence = []
|
72
|
+
end
|
73
|
+
|
74
|
+
shared_behaviors_for 'A'
|
75
|
+
before
|
76
|
+
before_sequence.push('A')
|
77
|
+
end
|
78
|
+
|
79
|
+
after
|
80
|
+
after_sequence.push('A')
|
81
|
+
end
|
82
|
+
|
83
|
+
before_each
|
84
|
+
before_each_sequence.push('A')
|
85
|
+
end
|
86
|
+
|
87
|
+
after_each
|
88
|
+
after_each_sequence.push('A')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
shared_behaviors_for 'B'
|
93
|
+
before
|
94
|
+
before_sequence.push('B')
|
95
|
+
end
|
96
|
+
|
97
|
+
after
|
98
|
+
after_sequence.push('B')
|
99
|
+
end
|
100
|
+
|
101
|
+
before_each
|
102
|
+
before_each_sequence.push('B')
|
103
|
+
end
|
104
|
+
|
105
|
+
after_each
|
106
|
+
after_each_sequence.push('B')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'before ordering'
|
111
|
+
should_behave_like('B')
|
112
|
+
|
113
|
+
before
|
114
|
+
before_sequence.push('C')
|
115
|
+
end
|
116
|
+
|
117
|
+
should_behave_like('A')
|
118
|
+
|
119
|
+
after
|
120
|
+
after_sequence.push('C')
|
121
|
+
end
|
122
|
+
|
123
|
+
before_each
|
124
|
+
before_each_sequence.push('C')
|
125
|
+
end
|
126
|
+
|
127
|
+
after_each
|
128
|
+
after_each_sequence.push('C')
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should sequence befores in include order"
|
132
|
+
before_sequence.should.eql ['B', 'C', 'A']
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should sequence before_eachs in include order"
|
136
|
+
before_each_sequence.should.eql ['B', 'A', 'C', 'B', 'A', 'C']
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe 'after ordering'
|
141
|
+
it "should sequence afters in include order"
|
142
|
+
after_sequence.should.eql ['B', 'A', 'C']
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should sequence after_eachs in include order"
|
146
|
+
after_each_sequence.should.eql ['B', 'A', 'C', 'B', 'A', 'C']
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
shared_behaviors_for 'person'
|
152
|
+
it 'should have a name'
|
153
|
+
person.should.have_property 'name'
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
shared_behaviors_for 'administrator'
|
158
|
+
should_behave_like('person')
|
159
|
+
|
160
|
+
it 'should have access to all permissions'
|
161
|
+
person.may('edit pages').should.be_true
|
162
|
+
person.may('delete users').should.be_true
|
163
|
+
end
|
164
|
+
end
|
1
165
|
|
2
166
|
describe 'Shared Behaviors'
|
3
167
|
describe 'User'
|
4
168
|
before
|
5
169
|
User = function(name) { this.name = name }
|
6
|
-
|
170
|
+
person = new User('joe')
|
7
171
|
end
|
8
172
|
|
9
|
-
|
10
|
-
|
173
|
+
should_behave_like('person')
|
174
|
+
end
|
175
|
+
|
176
|
+
describe 'Administrator'
|
177
|
+
before
|
178
|
+
Admin = function(name) { this.name = name }
|
179
|
+
Admin.prototype.may = function(perm){ return true }
|
180
|
+
person = new Admin('tj')
|
11
181
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
it 'should have access to all permissions'
|
23
|
-
user.may('edit pages').should.be_true
|
24
|
-
user.may('delete users').should.be_true
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'Super Administrator'
|
28
|
-
should_behave_like('Administrator')
|
29
|
-
|
30
|
-
before
|
31
|
-
SuperAdmin = function(name) { this.name = name }
|
32
|
-
SuperAdmin.prototype.may = function(perm){ return true }
|
33
|
-
user = new SuperAdmin('tj')
|
34
|
-
end
|
35
|
-
end
|
182
|
+
|
183
|
+
should_behave_like('administrator')
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'Super Administrator'
|
187
|
+
before
|
188
|
+
SuperAdmin = function(name) { this.name = name }
|
189
|
+
SuperAdmin.prototype.may = function(perm){ return true }
|
190
|
+
SuperAdmin.prototype.canCreateUsers = function(){ return true }
|
191
|
+
person = new SuperAdmin('tj')
|
36
192
|
end
|
193
|
+
|
194
|
+
should_behave_like('administrator')
|
195
|
+
|
196
|
+
it "should be allowed to create users"
|
197
|
+
person.canCreateUsers().should.be_true
|
198
|
+
end
|
37
199
|
end
|
38
200
|
|
39
|
-
|
201
|
+
shared_behaviors_for 'User with toString()'
|
40
202
|
before
|
41
|
-
|
203
|
+
person = { toString : function() { return '<User tj>' }}
|
42
204
|
end
|
43
205
|
|
44
206
|
it 'should return <User NAME>'
|
45
|
-
|
207
|
+
person.toString().should.match(/\<User/)
|
46
208
|
end
|
47
209
|
end
|
48
210
|
|
49
211
|
describe 'Manager'
|
50
|
-
should_behave_like('
|
212
|
+
should_behave_like('person')
|
51
213
|
should_behave_like('User with toString()')
|
52
214
|
|
53
215
|
before
|
54
216
|
Manager = function(name) { this.name = name }
|
55
217
|
Manager.prototype.may = function(perm){ return perm == 'hire' || perm == 'fire' }
|
56
218
|
Manager.prototype.toString = function(){ return '<User ' + this.name + '>' }
|
57
|
-
|
219
|
+
person = new Manager('tj')
|
58
220
|
end
|
59
221
|
|
60
222
|
it 'should have access to hire or fire employees'
|
61
|
-
|
62
|
-
|
63
|
-
|
223
|
+
person.may('hire').should.be_true
|
224
|
+
person.may('fire').should.be_true
|
225
|
+
person.may('do anything else').should.be_false
|
64
226
|
end
|
65
227
|
end
|
66
228
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
it 'should
|
73
|
-
JSpec.
|
74
|
-
end
|
75
|
-
|
229
|
+
describe 'findLocalSharedBehavior'
|
230
|
+
it 'should find shared behavior by name'
|
231
|
+
JSpec.findLocalSharedBehavior('User with toString()').should.be_a JSpec.Suite
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should return null when not found'
|
235
|
+
JSpec.findGlobalSharedBehavior('Rawr').should.be_null
|
236
|
+
end
|
237
|
+
|
238
|
+
describe 'nested'
|
239
|
+
it 'should find shared behavior by name when nested'
|
240
|
+
JSpec.findLocalSharedBehavior('User with toString()').should.be_a JSpec.Suite
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
describe 'findGlobalSharedBehavior'
|
246
|
+
it 'should find shared behavior by name'
|
247
|
+
JSpec.findGlobalSharedBehavior('person').should.be_a JSpec.Suite
|
248
|
+
end
|
249
|
+
|
76
250
|
it 'should return null when not found'
|
77
|
-
JSpec.
|
251
|
+
JSpec.findGlobalSharedBehavior('Rawr').should.be_null
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
describe 'findSharedBehavior'
|
256
|
+
shared_behaviors_for 'person'
|
257
|
+
it 'should not have name'
|
258
|
+
person.should.not.have_property 'name'
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe 'override behavior'
|
263
|
+
it 'should find local shared behavior before global'
|
264
|
+
JSpec.findSharedBehavior('person').body.toString().should.match(/should not have name/)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should find shared global behavior by name'
|
269
|
+
JSpec.findGlobalSharedBehavior('animal').should.be_a JSpec.Suite
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should return null when not found at either level'
|
273
|
+
JSpec.findGlobalSharedBehavior('Rawr').should.be_null
|
78
274
|
end
|
79
|
-
|
80
|
-
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
|
279
|
+
|
metadata
CHANGED
@@ -3,10 +3,10 @@ name: jspec
|
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
|
-
-
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version:
|
6
|
+
- 4
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 4.0.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- TJ Holowaychuk
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-22 00:00:00 -07:00
|
18
18
|
default_executable: jspec
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|