jspec 3.3.3 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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