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 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. For example an Admin, would inherit all specs of User:
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
- describe 'User'
370
- before
371
- User = function(name) { this.name = name }
372
- user = new User('joe')
373
- end
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
- **NOTE**: both User and Administrator's before hooks implement the 'user' variable
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
@@ -12,7 +12,7 @@ require 'src/installables'
12
12
  require 'src/server'
13
13
 
14
14
  program :name, 'JSpec'
15
- program :version, '3.3.3'
15
+ program :version, '4.0.0'
16
16
  program :description, 'JavaScript BDD Testing Framework'
17
17
  default_command :bind
18
18
 
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 = "3.3.3"
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-15}
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 : '3.3.3',
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.hasSpecs())
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.hasSpecs())
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.hasSpecs()) {
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
- hooks: { 'before' : [], 'after' : [], 'before_each' : [], 'after_each' : [] },
430
+ shared: isShared,
431
+ hooks: { 'before' : [], 'after' : [],
432
+ 'before_each' : [], 'after_each' : [],
433
+ 'before_nested' : [], 'after_nested' : []},
404
434
 
405
- // Add a spec to the suite
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
- // Invoke a hook in context to this suite
475
+ // Invoke a hook in context to this suite
432
476
 
433
477
  hook : function(hook) {
434
- if (this.suite) this.suite.hook(hook)
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
- try { return module[name].apply(module, args) }
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
- findSuite : function(description) {
737
- return find(this.allSuites, function(suite){
738
- return suite.name == description || suite.description == description
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
- if (suite = this.findSuite(description)) this.copySpecs(suite, this.currentSuite)
752
- else throw 'failed to share behaviors. ' + puts(description) + ' is not a valid Suite name'
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
- hook('evaluatingBody', dsl, matchers, context, contents)
1313
- try { with (dsl){ with (context) { with (matchers) { eval(contents) }}} }
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
- replace(/^ *(before_each|after_each|before|after)(?= |\n|$)/gm, 'JSpec.currentSuite.addHook("$1", function(){').
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
- this.currentSuite = suite
1399
- this.evalBody(suite.body)
1400
- suite.ran = true
1401
- hook('beforeSuite', suite), suite.hook('before')
1402
- each(suite.specs, function(spec) {
1403
- hook('beforeSpec', spec)
1404
- suite.hook('before_each')
1405
- JSpec.runSpec(spec)
1406
- hook('afterSpec', spec)
1407
- suite.hook('after_each')
1408
- })
1409
- if (suite.hasSuites()) {
1410
- each(suite.suites, function(suite) {
1411
- JSpec.runSuite(suite)
1412
- })
1413
- }
1414
- hook('afterSuite', suite), suite.hook('after')
1415
- this.stats.suitesFinished++
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
- error("failed to load `" + file + "'")
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
- //.exec('spec/unit/spec.fixtures.js') TODO: when exceptions bubble properly uncomment
15
+ .exec('spec/unit/spec.fixtures.js')
16
16
  .run({ reporter: JSpec.reporters.Terminal, failuresOnly: true, fixturePath: 'spec/fixtures' })
17
17
  .report()
@@ -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
@@ -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
- foo \
79
- bar \
80
- ').to(include, 'foo', 'bar')
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
- describe 'with tabs'
110
- before_each
111
- foo = 'bar'
112
- end
113
-
114
- it 'should work'
115
- foo.should.eql 'bar'
116
- end
117
-
118
- it 'should work'
119
- true.should.be true
120
- true.should.be(true)
121
- true.should.be(true);
122
- end
123
- end
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 1
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
- hits = []
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
- user = new User('joe')
170
+ person = new User('joe')
7
171
  end
8
172
 
9
- it 'should have a name'
10
- user.should.have_property 'name'
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
- describe 'Administrator'
14
- should_behave_like('User')
15
-
16
- before
17
- Admin = function(name) { this.name = name }
18
- Admin.prototype.may = function(perm){ return true }
19
- user = new Admin('tj')
20
- end
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
- describe 'User with toString()'
201
+ shared_behaviors_for 'User with toString()'
40
202
  before
41
- user = { toString : function() { return '<User tj>' }}
203
+ person = { toString : function() { return '<User tj>' }}
42
204
  end
43
205
 
44
206
  it 'should return &lt;User NAME&gt;'
45
- user.toString().should.match(/\<User/)
207
+ person.toString().should.match(/\<User/)
46
208
  end
47
209
  end
48
210
 
49
211
  describe 'Manager'
50
- should_behave_like('User')
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
- user = new Manager('tj')
219
+ person = new Manager('tj')
58
220
  end
59
221
 
60
222
  it 'should have access to hire or fire employees'
61
- user.may('hire').should.be_true
62
- user.may('fire').should.be_true
63
- user.may('do anything else').should.be_false
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
- describe 'findSuite'
68
- it 'should find a suite by full description'
69
- JSpec.findSuite('Shared Behaviors User Administrator').should.be_a JSpec.Suite
70
- end
71
-
72
- it 'should find a suite by name'
73
- JSpec.findSuite('User').should.be_a JSpec.Suite
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.findSuite('Rawr').should.be_null
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
- end
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
- - 3
7
- - 3
8
- - 3
9
- version: 3.3.3
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-15 00:00:00 -07:00
17
+ date: 2010-03-22 00:00:00 -07:00
18
18
  default_executable: jspec
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency