Compare commits

...

125 Commits

Author SHA1 Message Date
Gregg Van Hove
3b53e469fd Bump version to 2.4.0 2015-12-02 22:02:03 -08:00
Gregg Van Hove
b3f69852c1 Merge pull request #973 from brunoqc/patch-1
Syntax highlighting in README.md
2015-11-13 17:05:28 -08:00
Bruno Bigras
1613a376b1 Syntax highlighting in README.md 2015-11-12 12:10:21 -05:00
Gregg Van Hove
1e35e8ba95 Use git:// url for jasmine-npm dependency 2015-11-04 15:12:38 -08:00
Gregg Van Hove
a6b209bc2f Use jasmine-npm straight from github when developing 2015-11-04 15:05:07 -08:00
Gregg Van Hove
2301914549 build combined file for jsApiReporter changes
[#92249258]
2015-11-04 14:11:39 -08:00
Gregg Van Hove
320c42b6cc Run jasmine's specs randomly in node and performance specs
[#92249258]
2015-11-04 12:30:49 -08:00
Gregg Van Hove
df45b4fede Run jasmine's specs in random order
[#92249258]
2015-11-04 12:06:28 -08:00
Gregg Van Hove
c1ab3c9cbe Add support for returning run details for reporting randomness
[#92249258]
2015-11-04 12:05:29 -08:00
Gregg Van Hove
d2f2e2b870 Merge branch 'himajasuman-issue#896'
Fixes #896
2015-10-27 14:13:15 -07:00
Gregg Van Hove
0f6a7f04b3 Merge branch 'issue#896' of https://github.com/himajasuman/jasmine into himajasuman-issue#896 2015-10-27 14:12:31 -07:00
Gregg Van Hove
728af5e556 Remove unused queueableFn arg from onException
Fixes #958
2015-10-27 12:24:32 -07:00
Gregg Van Hove
018fd53c10 Merge branch 'FuzzySockets-to-throw-error-unused-param' 2015-10-27 12:22:09 -07:00
Gregg Van Hove
25d73515f3 Merge branch 'to-throw-error-unused-param' of https://github.com/FuzzySockets/jasmine into FuzzySockets-to-throw-error-unused-param 2015-10-27 12:21:42 -07:00
Gregg Van Hove
8e317d4026 Less verbose for the linter 2015-10-26 17:51:42 -07:00
Gregg Van Hove
ea4c44904d IE 8 doesn't support defineProperty on non-DOM nodes, skip that kindof thing 2015-10-26 17:41:30 -07:00
Gregg Van Hove
77514bbb80 use safari 9 not 8.1 anymore 2015-10-26 17:18:25 -07:00
Gregg Van Hove
a85c3a4da8 Check for descriptor 2015-10-26 17:03:45 -07:00
Gregg Van Hove
0b1e1a0401 Merge branch 'StephanBijzitter-throw-for-constants'
Fixes #948
2015-10-26 16:30:01 -07:00
Gregg Van Hove
3374415add Merge pull request #954 from matthewhuff89/remove_goals_md
Removed GOALS_2.0.md, doesn't seem to be needed anymore
2015-10-26 14:58:03 -07:00
Richard Harrington
c2ae3b6b12 Remove unused parameter from toThrowError 2015-10-26 11:43:31 -04:00
Himaja
110cacab19 Added a throw error block in describe incase a function with arguments is passed in describe 2015-10-25 14:13:14 -04:00
Matthew D. Huff
db7879a478 Removed GOALS_2.0.md, doesn't seem to be needed anymore 2015-10-25 13:03:46 -04:00
Stephan Bijzitter
a81466d9e7 Abort spying when the target cannot be spied on 2015-10-21 12:44:52 +02:00
Gregg Van Hove
48f42eaa7d Merge branch 'lalunamel-master'
Merges #942
Fixes #930
Fixes #912
2015-10-15 09:21:57 -07:00
Cody Sehl
e5c2572753 Change #xit so that it will output a more BDD-style pending message 2015-10-14 21:03:47 -06:00
Gregg Van Hove
141fd910f2 Use className instead of class when creating DOM elements 2015-10-06 09:10:22 -07:00
Gregg Van Hove
a93bfd2120 Merge branch 'marcioj-random-tests' 2015-10-04 14:03:30 -07:00
Gregg Van Hove
4221b2d2c4 Merge branch 'random-tests' of https://github.com/marcioj/jasmine into marcioj-random-tests 2015-10-04 14:03:17 -07:00
Gregg Van Hove
6ee7fd6ced Merge branch 'toString_fallback' of https://github.com/myitcv/jasmine into myitcv-toString_fallback 2015-10-04 13:47:27 -07:00
Gregg Van Hove
878325e2cf Merge branch 'James-Dunn-patch-1' 2015-10-04 13:45:10 -07:00
James
80c4f87dd5 Fix circles/x from getting cut off on Mac/chrome 2015-09-27 17:01:08 +04:00
Marcio Junior
3f3fa484b2 Allow tests to run in random order 2015-09-26 14:53:08 -03:00
Paul Jolly
d0ad9b98cd Use toString for objects if it has been overriden 2015-09-25 20:19:48 +01:00
Gregg Van Hove
375a6f9fda Merge branch 'danielalexiuc-master'
- Fixes #924
- Fixes #917
2015-09-24 12:58:56 -07:00
danielalexiuc
c017f0000d Postpone find() until it is needed
This is a fix for issue #917.

It seems that 'symbols' was originally included as a performance optimization, to avoid repeated find() calls for '.jasmine-symbol-summary'. However this find() occasionally fails during initialize if the dom has not loaded completely.

This change will not affect performance, as symbols is still cached. However it improves upon the original code in that the find happens at a stage much later than initialize.
2015-09-16 11:52:05 +10:00
Gregg Van Hove
4097718b66 Merge pull request #906 from soycode/master
check for global before assigning
2015-09-03 13:38:21 -07:00
Gregg Van Hove
825dab32ff Merge pull request #908 from mcamac/master
Reverse suite afterEach behavior to match semantics?
2015-09-01 21:33:52 -07:00
Martin Camacho
f3a7396845 afterEach behavior 2015-08-18 17:55:03 -04:00
soycode
850bee5492 check for global before assigning 2015-08-17 14:20:52 -07:00
Gregg Van Hove
6028a5d92c Merge branch 'SimenB-badges' 2015-08-10 10:39:39 -07:00
Simen Bekkhus
93a13ab791 Use badges from shields.io 2015-08-08 07:54:15 +02:00
Greg Chattin-McNichols and Gregg Van Hove
542f483228 Force the safari 8.1 version to be a string for sauce 2015-08-04 15:11:39 -07:00
Greg Chattin-McNichols and Gregg Van Hove
459b4c29b6 Drop Safari 5 on OS-X from the build matrix
- SauceLabs no longer supports it
- Add Safari 8.1
2015-08-04 09:40:37 -07:00
Greg Chattin-McNichols and Gregg Van Hove
750a9aac6d Merge pull request #869 from ljwall/jasmine
Fixes #855
2015-08-03 15:01:43 -07:00
Greg Chattin-McNichols and Gregg Van Hove
cd55f03912 concat files for toHaveBeenCalledTimes matcher 2015-08-03 14:57:52 -07:00
Gregg Van Hove
79954311fb Merge pull request #892 from obastemur/patch-1
Update glob to latest
2015-07-16 12:10:21 -07:00
Oguz Bastemur
3f71bcdb2d Update glob to latest
Fixes https://github.com/jasmine/jasmine/issues/891
2015-07-15 02:37:36 +03:00
Gregg Van Hove
06f05ac57b Add notes about "ready for work" label 2015-07-02 14:52:17 -07:00
Gregg Van Hove
5ea5ec6004 Merge branch 'kkirsche-patch-1' 2015-06-12 13:25:37 -07:00
Kevin Kirsche
f7033f6551 Remove moot version property from bower.json
Per bower/bower.json-spec@a325da3
2015-06-10 18:36:17 -04:00
Gregg Van Hove
7e6e905814 Merge branch 'logankd-toHaveBeenCalledTimes'
Fixes #871
2015-06-05 21:09:51 -07:00
Kevin
a6a1962924 add toHaveBeenCalledTimes matcher
Fix #853
2015-06-05 21:07:24 -07:00
Gregg Van Hove
50944fea6f Mention use of bundle exec for running the jasmine server during dev 2015-06-05 20:36:56 -07:00
Liam Wall
7bfc4c0a45 xdescribe marks pending, plus associated tests. 2015-05-29 17:21:28 +01:00
Gregg Van Hove and Noah Denton
4be2079482 Use the travis sauce connect addon 2015-05-18 17:04:21 -07:00
Gregg Van Hove
d6f47ea886 Merge pull request #856 from lpww/patch-1
Update CONTRIBUTING.md
2015-05-18 14:29:44 -07:00
Gregg Van Hove
5061dd066c Merge branch 'unique-css-classes' of https://github.com/prather-mcs/jasmine into prather-mcs-unique-css-classes 2015-05-18 14:29:03 -07:00
Gregg Van Hove
2a847a67e3 Merge branch 'danfinnie-any-vs-anything-error' 2015-05-18 14:27:27 -07:00
Thomas Treffry
50223d97d6 Update CONTRIBUTING.md
Rephrase confusing statement:

From:
If when you run ($ grunt)...you see that JSHint runs your system is ready.

To:
Now run ($ grunt)...if you see that JSHint runs, your system is ready.
2015-05-17 11:49:39 -07:00
Dan Finnie
302e78f1df Raise an error when jasmine.any() isn't passed a constructor 2015-05-17 02:21:26 -04:00
Matt Prather
42ad12ec52 Make the HtmlReport CSS classes "unique enough"
The only difference between this commit and the previous is that I have
used a difference scheme for naming Jasmine CSS classes.

Instead of appending "_jasmine-css" to all Jasmine CSS selectors, I have
now preprended "jasmine-" instead.
2015-05-14 14:23:06 -07:00
Matt Prather
c41fa7d156 Make the HtmlReport CSS classes "unique enough"
As described in Issue Report 844...
https://github.com/jasmine/jasmine/issues/844

...style rules in the app-being-tested may incidentally affect elements
in the Jasmine HTML Report container, as long as there is a chance that
the app-being-tested has CSS style rules for classes (or IDs) that
Jasmine uses.

This fix attempts to bring Jasmine to a state where each and every class
it uses always ends with "_jasmine-css" which should be unique enough to
ensure that CSS in the app-being-tested won't affect the Jasmine report,
because no app-being-tested is ever likely to use classes that end with
"_jasmine-css"

I'll be surpised if this commit is good enough as it is now, on the
first attempt to fix #844, because of reasons I'll explain in either
the Issue or the Pull Request.
2015-05-13 18:55:44 -07:00
Gregg Van Hove
0b1449228f Bump version to 2.3.4 2015-05-13 14:57:56 -07:00
Gregg Van Hove
65a6decd6d Fix ordering for suites with more than 11 direct children.
- When no specs were focused, they all had the same precedence, and
  `sort`ing them caused some of the nodes to move around

Fixes #850
2015-05-13 14:45:11 -07:00
Gregg Van Hove
7cbd86357d Merge branch 'remove-dead-css' of https://github.com/prather-mcs/jasmine into prather-mcs-remove-dead-css 2015-05-13 11:03:25 -07:00
Gregg Van Hove
4f278be2c2 Update standalone installation instructions to reference the releases page
Fix #603
2015-05-13 10:59:39 -07:00
Matt Prather
f2bc9b5bd8 Remove the style rule for .running-alert CSS class
https://github.com/jasmine/jasmine/issues/847#issuecomment-101446573
2015-05-12 15:51:42 -07:00
Gregg Van Hove
e9d79bc946 Merge branch 'prather-mcs-remove-dead-css' 2015-05-11 10:59:36 -07:00
Gregg Van Hove
0b2097b616 Bump version to 2.3.3 2015-05-11 10:48:58 -07:00
Gregg Van Hove
f02824ae52 Merge branch 'remove-dead-css' of https://github.com/prather-mcs/jasmine into prather-mcs-remove-dead-css 2015-05-11 10:41:18 -07:00
Robert Neumann
225c7bdda3 Set the shared user context correctly when executing the top level suite
Fixes #846
2015-05-11 10:29:51 -07:00
Matt Prather
e855c898d1 Remove dead CSS class styles
I removed the `.showDetails` and `.summaryMenuItem` styles from the Sass
file because I believe that no HTML elements with those classes will
ever be generated by Jasmine and that they are dead code that someone
forgot to remove.

This is my first contribution to the Jasmine project and so I might be
doing something wrong, but I believe just this one change will propagate
to all the generated code when it is built, and that I should not be
altering any other code in any other place to accomplish the change I
intend.

This is related to Jasmine Issue 847:
https://github.com/jasmine/jasmine/issues/847
2015-05-10 16:58:07 -07:00
Gregg Van Hove
426eebe1ce bump version to 2.3.2 2015-05-07 14:02:12 -07:00
Gregg Van Hove
add841a1e9 A spec without a function provided should be pending not disabled
Fixes #840
2015-05-07 13:46:52 -07:00
Gregg Van Hove
023c998660 use a link for the PR in release notes 2015-05-05 07:51:49 -07:00
Gregg Van Hove
3dde7d0c29 Bump version to 2.3.1 to create a new bower package 2015-05-05 07:48:49 -07:00
Gregg Van Hove
4e3f9a4d09 Merge pull request #843 from evoL/fix-bower-package
Make the Bower package use browser-friendly files.
2015-05-05 07:22:25 -07:00
Rafał Hirsz
b89fbc71a7 Point Bower's main field to jasmine.js, which is browser-friendly. 2015-05-05 15:36:24 +02:00
Gregg Van Hove
4c0e3b2aed remove dist zips from the repo. They should all be available on github releases 2015-04-28 13:43:21 -07:00
Gregg Van Hove
19f812c4f6 Fix cp command for release documentation 2015-04-28 11:27:03 -07:00
Gregg Van Hove
5ea24a8448 version bump to 2.3.0 2015-04-28 10:13:42 -07:00
Gregg Van Hove
4173a4089c Merge pull request #827 from davetron5000/patch-1
Explicitly state the main JS
2015-04-19 10:03:19 -07:00
David Copeland
f712b795d7 Explicitly state the main JS
# Problem

To bring this lib in using Sprockets, you must do this:

```javascript
//= require jasmine/lib/jasmine-core
```

Sprockets can read `bower.json` and, if `main` is explicitly stated in the file, you can do the much more future-proof and compact:


```javascript
//= require jasmine
```

# Solution

Explicitly specify it.

# Caveats

I am not super-versed in Bower or JS packaging, so this is proposed in the vein of "this fixes my problem and seems consistent with other JS libs I've looked at", but I'm open to other solutions.
2015-04-19 12:22:33 -04:00
Gregg Van Hove
ff029b37b5 Use instanceof when checking Error types in toThrowError
Fixes #819
2015-04-09 15:38:24 -07:00
Gregg Van Hove
7cd8c41d31 Merge pull request #818 from lpww/patch-1
Update formatting
2015-04-05 21:56:59 -07:00
Thomas Treffry
d7dd85c64f Update formatting
Remove periods from bullet points for consistency with rest of document
2015-04-05 20:19:29 -07:00
Davis W. Frank
2d5c071d28 Merge pull request #815 from jhamon/contributing-subjective-readability-improvements
Subjective readability improvements to CONTRIBUTING.md
2015-04-02 08:49:39 -07:00
Jen Hamon
76bc0a87db Use code fence syntax around git workflow for readability. 2015-04-01 13:25:32 -07:00
Jen Hamon
5cae401c98 Pull urls out of paragraph to improve readability 2015-04-01 13:06:58 -07:00
Gregg Van Hove
1d366772b7 Don't throw if we're already handling an exception
[finish #91407284]
2015-03-30 08:19:06 -07:00
Gregg Van Hove and Nikhil Gajwani
d137b83c1c Don't install the clock if the current timing functions aren't the originals
[finish #64116664] Fix #782
2015-03-27 10:14:03 -07:00
Gregg Van Hove
692c8716f0 Style disabled specs in the results list 2015-03-26 15:45:26 -07:00
Gregg Van Hove
965229bd03 Properly pass j$ to Any so it can use other jasmine stuff
Fixes #806
2015-03-18 13:12:40 -07:00
Gregg Van Hove
46044dd345 Merge branch 'sgravrock-clock-reset' 2015-03-15 13:23:56 -07:00
Steve Gravrock
2af9a45fb2 Correctly handle functions that are scheduled after the clock is uninstalled and reinstalled from within Clock#tick.
Fixes #790.
2015-03-14 17:40:27 -07:00
Gregg Van Hove
abc0c4a97e Update to ruby 2.x for travis builds
- sauce gem allowed cmdparse to upgrade a major version and 3.0 of
  cmdparse requires ruby >= 2.0.0
2015-03-14 15:26:46 -07:00
slackersoft
eb1d98338a Properly inject j$ into Suite 2015-03-06 11:43:57 -08:00
slackersoft
f0c480f456 Use onclick directly to better support older webkit 2015-03-06 10:09:08 -08:00
Gregg Van Hove and Molly Trombley-McCann
7693a4c959 Allow user to stop a specs execution when an expectation fails
[finish #1165916] #577
2015-03-05 15:28:00 -08:00
Gregg Van Hove
1a08d1e8c6 Don't use deprecated onComplete syntax for jasmine-npm 2015-03-04 17:44:05 -08:00
Gregg Van Hove
ce9600a3f6 Allow the clock to be installed for the duration of a single closure
[finish #67434180]
2015-03-04 17:41:49 -08:00
Gregg Van Hove and Molly Trombley-McCann
c58d83bbe3 Merge branch 'remove-unnecessary-conditional' of https://github.com/toddbranch/jasmine into toddbranch-remove-unnecessary-conditional 2015-03-04 12:00:07 -08:00
Gregg Van Hove and Molly Trombley-McCann
1c6f4ef0e6 Build distribution for previous changes 2015-03-04 11:58:47 -08:00
Gregg Van Hove
c77ff30263 Show the name of the constructor function when printing an any
- instead of a `toString` of the entire constructor

Fixes #796
2015-03-03 13:27:31 -08:00
Gregg Van Hove
dc652cfb05 Clean up some TreeProcessor stuff.
- Properly segment parents of segmented suites
2015-03-03 13:14:20 -08:00
Gregg Van Hove
22f58c0049 Merge pull request #789 from sgravrock/safe-temp-dir
Don't use hardcoded temporary directory paths
2015-03-02 13:59:26 -08:00
slackersoft
715de7aa38 Implement TreeProcessor to solve some issues with running the suite
- execute beforeAll/afterAll once per suite instead of once per child
  when running focused specs/suites Fixes #773
- refuse to execute an order if it would cause a suite with a beforeAll
  or afterAll to be re-entered after leaving once
- report children of an xdescribe similarly to how they would be
  reported if they were themselves x'd out Fixes #774
- only process the tree once instead of figuring it out again at each
  level

[finishes #87545620]
Fixes #776
2015-03-02 11:41:45 -08:00
slackersoft
0c68cc4afc Fix spec so it can be run in isolation
relates to #790
2015-02-27 16:57:23 -08:00
slackersoft
ce6ce4e2c7 Add safari 7 & 8 to browser matrix 2015-02-27 13:44:55 -08:00
Greg Cobb
10f87b3b90 Fixes issue where mock clock was being used by QueueRunner
- If the mock clock was installed in a beforeAll, the QueueRunner would use the mock clock for its own clock.  If the mock clock was ticked more than the default timeout, async specs would timeout.

[fixes #783 #792]
2015-02-24 21:56:52 -05:00
Steve Gravrock
0776146d3b Don't use hardcoded temporary directory paths 2015-02-22 16:03:20 -08:00
Todd Branchflower
bbac4bb23f remove unnecessary conditional 2015-02-20 14:04:08 -07:00
Gregg Van Hove
8c59875afe Merge pull request #775 from joscha/patch-1
add missing semicolon
2015-02-09 09:54:54 -08:00
Joscha Feth
cdee9c8853 add missing semicolon 2015-02-09 15:40:41 +01:00
Greg Cobb and Gregg Van Hove
69956bf8f6 ObjectContaining matches prototype properties
[#769]
2015-02-05 14:15:57 -08:00
Christopher Amavisca
e1249ac89a Remove unused standaloneBuilder var from Gruntfile 2015-02-04 17:06:56 -08:00
Christopher Amavisca
a84e0cd8ef Add test script to package.json
- Use `npm test` in travis-node-script
2015-02-04 16:55:07 -08:00
Christopher Amavisca
6177a4aeff Update bower.json keywords to match package.json keywords 2015-02-04 16:36:43 -08:00
Christopher Amavisca
471a241493 Add keywords to package.json 2015-02-04 16:36:31 -08:00
Greg Cobb and Gregg Van Hove
d5dfbc98c3 Updates pretty printer to include array properties
[fixes #766][finishes #87644044]
2015-02-04 11:05:03 -08:00
Gregg Van Hove
2ab2a83a3b Merge pull request #768 from danilovaz/master
Update year copyright
2015-02-04 09:58:40 -08:00
Greg Cobb and Gregg Van Hove
f22862fd80 Merge branch 'juliemr-arrayfix'
Fixes #765
2015-02-04 09:38:45 -08:00
Julie Ralph
53b0752ff0 Allow arrays from different frames or contexts to be equal 2015-02-04 09:28:04 -08:00
Danilo Vaz
7616e5a3fd Update year copyright 2015-02-04 08:42:18 -02:00
82 changed files with 3976 additions and 1168 deletions

2
.gitignore vendored
View File

@@ -20,5 +20,5 @@ sauce_connect.log
*.swp
build/
*.egg-info/
dist/*.tar.gz
dist
nbproject/

View File

@@ -2,7 +2,7 @@ language: ruby
sudo: false
rvm: 1.9.3
rvm: 2.2.0
script: $TEST_COMMAND
@@ -17,6 +17,9 @@ env:
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
addons:
sauce_connect: true
matrix:
include:
- env:
@@ -24,12 +27,20 @@ matrix:
- TEST_COMMAND="bash travis-node-script.sh"
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.8"
- SAUCE_BROWSER_VERSION=6
- SAUCE_OS="OS X 10.11"
- SAUCE_BROWSER_VERSION=9
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.6"
- SAUCE_BROWSER_VERSION=5
- SAUCE_OS="OS X 10.10"
- SAUCE_BROWSER_VERSION=8
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.9"
- SAUCE_BROWSER_VERSION=7
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.8"
- SAUCE_BROWSER_VERSION=6
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8.1"

View File

@@ -1,23 +1,28 @@
# Developing for Jasmine Core
We welcome your contributions - Thanks for helping make Jasmine a better project for everyone. Please review the backlog and discussion lists (the main group - [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js) and the developer's list - [http://groups.google.com/group/jasmine-js-dev](http://groups.google.com/group/jasmine-js-dev)) before starting work - what you're looking for may already have been done. If it hasn't, the community can help make your contribution better.
We welcome your contributions! Thanks for helping make Jasmine a better project for everyone. Please review the backlog and discussion lists before starting work. What you're looking for may already have been done. If it hasn't, the community can help make your contribution better. If you want to contribute but don't know what to work on, [issues tagged ready for work](https://github.com/jasmine/jasmine/labels/ready%20for%20work) should have enough detail to get started.
## Links
- [Jasmine Google Group](http://groups.google.com/group/jasmine-js)
- [Jasmine-dev Google Group](http://groups.google.com/group/jasmine-js-dev)
- [Jasmine on PivotalTracker](https://www.pivotaltracker.com/n/projects/10606)
## General Workflow
Please submit pull requests via feature branches using the semi-standard workflow of:
1. Fork it
1. Clone your fork: (`git clone git@github.com:yourUserName/jasmine.git`)
1. Change directory: (`cd jasmine`)
1. Assign original repository to a remote named 'upstream': (`git remote add
upstream https://github.com/jasmine/jasmine.git`)
1. Pull in changes not present in your local repository: (`git fetch upstream`)
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Commit your changes (`git commit -am 'Add some feature'`)
1. Push to the branch (`git push origin my-new-feature`)
1. Create new Pull Request
```bash
git clone git@github.com:yourUserName/jasmine.git # Clone your fork
cd jasmine # Change directory
git remote add upstream https://github.com/jasmine/jasmine.git # Assign original repository to a remote named 'upstream'
git fetch upstream # Pull in changes not present in your local repository
git checkout -b my-new-feature # Create your feature branch
git commit -am 'Add some feature' # Commit your changes
git push origin my-new-feature # Push to the branch
```
We favor pull requests with very small, single commits with a single purpose.
Once you've pushed a feature branch to your forked repo, you're ready to open a pull request. We favor pull requests with very small, single commits with a single purpose.
## Background
@@ -77,11 +82,11 @@ To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http:/
$ npm install --local
...will install all of the node modules locally. If when you run
...will install all of the node modules locally. Now run
$ grunt
...you see that JSHint runs your system is ready.
...if you see that JSHint runs, your system is ready.
### How to write new Jasmine code
@@ -100,7 +105,7 @@ Follow these tips and your pull request, patch, or suggestion is much more likel
Jasmine uses the [Jasmine Ruby gem](http://github.com/jasmine/jasmine-gem) to test itself in browser.
$ rake jasmine
$ bundle exec rake jasmine
...and then visit `http://localhost:8888` to run specs.
@@ -118,8 +123,8 @@ Jasmine uses the [Jasmine NPM package](http://github.com/jasmine/jasmine-npm) to
## Submitting a Pull Request
1. Revert your changes to `jasmine.js` and `jasmine-html.js`
* We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches.
1. When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master.
* We do this because `jasmine.js` and `jasmine-html.js` are auto-generated (as you've seen in the previous steps) and accepting multiple pull requests when this auto-generated file changes causes lots of headaches
1. When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master
Note that we use Travis for Continuous Integration. We only accept green pull requests.

View File

@@ -1,64 +0,0 @@
# (Vague) Jasmine 2.0 Goals/(Guidelines)
1. No globals!
* jasmine library is entirely inside `jasmine` namespace
* globals required for backwards compatibility should be added in `boot.js` (EG, var describe = jasmine.getCurrentEnv().describe lives in boot.js)
1. Don't use properties as getters. Use methods.
* Properties aren't encapsulated -- can be mutated, unsafe.
1. Reporters get data objects (no methods).
* easier to refactor as needed
1. More unit tests - fewer nasty integration tests
## Remaining non-story-able work:
* Make a `TODO` list
### Hard
* Finish killing Globals
* Guidelines:
* New objects can have constructors on `jasmine`
* Top level functions can live on `jasmine`
* Top level (i.e., any `jasmine` property) should only be referenced inside the `Env` constructor
* should better allow any object to get jasmine code (Node-friendly)
* review everything in base.js
* Remove isA functions:
* isArray_ - used in matchers and spies
* isString_
* isDOMNode_
* isA_
* unimplementedMethod_, used by PrettyPrinter
* jasmine.util should be util closure inside of env or something
* argsToArray is used for Spies and matching (and can be replaced)
* inherit is only for PrettyPrinter now
* formatException is used only inside Env/spec
* htmlEscape is for messages in matchers - should this be HTML at all?
* Pretty printing
* move away from pretty printer and to a JSON.stringify implementation?
* jasmineToString vs. custom toString ?
### Easy
* unify params to ctors: options vs. attrs.
* This will be a lot of the TODOs, but clean up & simplify Env.js (is this a 2.1 task?)
### DONE
* Matchers improvements
* unit testable DONE
* better equality (from Underscore) DONE
* addCustomMatchers doesn't explode stack DONE
* refactor equals function so that it just loops & recurses over a list of fns (custom and built-in) - 2.1? (Tracker story)
* Spies
* break these out into their own tests/file DONE
## Other Topics
* Docs
* Docco has gone over well. Should we annotate all the sources and then have Pages be more complex, having tutorials and annotated source like Backbone? Are we small enough?
* Need examples for:
* How to build a Custom Matcher
* How to add a custom equality tester

View File

@@ -17,7 +17,6 @@ module.exports = function(grunt) {
grunt.registerTask('default', ['jshint:all']);
var version = require('./grunt/tasks/version.js');
var standaloneBuilder = require('./grunt/tasks/build_standalone.js');
grunt.registerTask('build:copyVersionToGem',
"Propagates the version from package.json to version.rb",
@@ -43,10 +42,8 @@ module.exports = function(grunt) {
jasmine = new Jasmine({jasmineCore: jasmineCore});
jasmine.loadConfigFile('./spec/support/jasmine.json');
jasmine.configureDefaultReporter({
onComplete: function(passed) {
done(passed);
}
jasmine.onComplete(function(passed) {
done(passed);
});
jasmine.execute();

View File

@@ -1,6 +1,7 @@
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/master/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
[![Build Status](https://travis-ci.org/jasmine/jasmine.png?branch=master)](https://travis-ci.org/jasmine/jasmine) [![Code Climate](https://codeclimate.com/github/pivotal/jasmine.png)](https://codeclimate.com/github/pivotal/jasmine)
[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine)
[![Code Climate](https://codeclimate.com/github/pivotal/jasmine.svg)](https://codeclimate.com/github/pivotal/jasmine)
=======
@@ -28,22 +29,24 @@ For the Jasmine Ruby Gem:<br>
For the Jasmine Python Egg:<br>
[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py)
To install Jasmine on your local box:
To install Jasmine standalone on your local box:
* Clone Jasmine - `git clone https://github.com/jasmine/jasmine.git`
* Download the standalone distribution for your desired release from the [releases page](https://github.com/jasmine/jasmine/releases)
* Create a Jasmine directory in your project - `mkdir my-project/jasmine`
* Move latest dist to your project directory - `mv jasmine/dist/jasmine-standalone-2.0.0.zip my-project/jasmine`
* Move the dist to your project directory - `mv jasmine/dist/jasmine-standalone-2.0.0.zip my-project/jasmine`
* Change directory - `cd my-project/jasmine`
* Unzip the dist - `unzip jasmine-standalone-2.0.0.zip`
Add the following to your HTML file:
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-2.0.0/jasmine.css">
```html
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-2.0.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-2.0.0/jasmine.css">
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/boot.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-2.0.0/boot.js"></script>
```
## Supported environments
@@ -62,10 +65,12 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, a
* [Davis W. Frank](mailto:dwfrank@pivotal.io), Pivotal Labs
* [Rajan Agaskar](mailto:rajan@pivotal.io), Pivotal Labs
* [Gregg Van Hove](mailto:gvanhove@pivotal.io), Pivotal Labs
* [Greg Cobb](mailto:gcobb@pivotal.io), Pivotal Labs
* [Chris Amavisca](mailto:camavisca@pivotal.io), Pivotal Labs
### Maintainers Emeritus
* [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
* Sheel Choksi
Copyright (c) 2008-2014 Pivotal Labs. This software is licensed under the MIT License.
Copyright (c) 2008-2015 Pivotal Labs. This software is licensed under the MIT License.

View File

@@ -15,7 +15,7 @@ Please attempt to keep commits to `master` small, but cohesive. If a feature is
We attempt to stick to [Semantic Versioning](http://semver.org/). Most of the time, development should be against a new minor version - fixing bugs and adding new features that are backwards compatible.
The current version lives in the file `/package.json`. This version will be the version number that is currently released. When releasing a new version, update `package.json` and `bower.json` with the new version and `grunt build:copyVersionToGem` to update the gem version number.
The current version lives in the file `/package.json`. This version will be the version number that is currently released. When releasing a new version, update `package.json` with the new version and `grunt build:copyVersionToGem` to update the gem version number.
This version is used by both `jasmine.js` and the `jasmine-core` Ruby gem.
@@ -37,8 +37,6 @@ When ready to release - specs are all green and the stories are done:
### Build standalone distribution
1. Build the standalone distribution with `grunt buildStandaloneDist`
1. Make sure you add the new ZIP file to git
1. Should we still do this? Given we want to use github releases...
### Release the Python egg
@@ -61,7 +59,7 @@ When ready to release - specs are all green and the stories are done:
Probably only need to do this when releasing a minor version, and not a patch version.
1. `cp edge ${version}` to copy the current edge docs to the new version
1. `cp -R edge ${version}` to copy the current edge docs to the new version
1. Add a link to the new version in `index.html`
### Finally

View File

@@ -1,17 +1,19 @@
{
"name": "jasmine-core",
"version": "2.2.1",
"homepage": "http://jasmine.github.io",
"authors": [
"slackersoft <gregg@slackersoft.net>"
],
"description": "Official packaging of Jasmine's core files",
"keywords": [
"test",
"jasmine",
"tdd",
"bdd"
],
"license": "MIT",
"moduleType": "globals",
"main": "lib/jasmine-core/jasmine.js",
"ignore": [
"**/.*",
"dist",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -26,6 +26,7 @@ module.exports = {
'src/core/base.js',
'src/core/util.js',
'src/core/Spec.js',
'src/core/Order.js',
'src/core/Env.js',
'src/core/JsApiReporter.js',
'src/core/PrettyPrinter',

View File

@@ -57,13 +57,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var jasmineInterface = jasmineRequire.interface(jasmine, env);
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
* Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
extend(window, jasmineInterface);
/**
* ## Runner Parameters
@@ -78,6 +74,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var random = queryString.getParam("random");
env.randomizeTests(random);
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
}
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
@@ -85,6 +92,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },

View File

@@ -35,13 +35,9 @@
var jasmineInterface = jasmineRequire.interface(jasmine, env);
/**
* Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
* Add all of the Jasmine global/public interface to the global scope, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
*/
if (typeof window == "undefined" && typeof exports == "object") {
extend(exports, jasmineInterface);
} else {
extend(window, jasmineInterface);
}
extend(window, jasmineInterface);
/**
* ## Runner Parameters
@@ -56,6 +52,17 @@
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var random = queryString.getParam("random");
env.randomizeTests(random);
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
}
/**
* ## Reporters
* The `HtmlReporter` builds all of the HTML UI for the runner page. This reporter paints the dots, stars, and x's for specs, as well as all spec names and all failures (if any).
@@ -63,6 +70,8 @@
var htmlReporter = new jasmine.HtmlReporter({
env: env,
onRaiseExceptionsClick: function() { queryString.navigateWithNewParam("catch", !env.catchingExceptions()); },
onThrowExpectationsClick: function() { queryString.navigateWithNewParam("throwFailures", !env.throwingExpectationFailures()); },
onRandomClick: function() { queryString.navigateWithNewParam("random", !env.randomTests()); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },

View File

@@ -7,7 +7,7 @@ beforeEach(function () {
return {
pass: player.currentlyPlayingSong === expected && player.isPlaying
}
};
}
};
}

View File

@@ -40,6 +40,8 @@ jasmineRequire.HtmlReporter = function(j$) {
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
onRandomClick = options.onRandomClick || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
timer = options.timer || noopTimer,
results = [],
@@ -53,19 +55,17 @@ jasmineRequire.HtmlReporter = function(j$) {
this.initialize = function() {
clearPrior();
htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
createDom('div', {className: 'banner'},
createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}),
createDom('span', {className: 'version'}, j$.version)
createDom('div', {className: 'jasmine-banner'},
createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}),
createDom('span', {className: 'jasmine-version'}, j$.version)
),
createDom('ul', {className: 'symbol-summary'}),
createDom('div', {className: 'alert'}),
createDom('div', {className: 'results'},
createDom('div', {className: 'failures'})
createDom('ul', {className: 'jasmine-symbol-summary'}),
createDom('div', {className: 'jasmine-alert'}),
createDom('div', {className: 'jasmine-results'},
createDom('div', {className: 'jasmine-failures'})
)
);
getContainer().appendChild(htmlReporterMain);
symbols = find('.symbol-summary');
};
var totalSpecsDefined;
@@ -74,7 +74,7 @@ jasmineRequire.HtmlReporter = function(j$) {
timer.start();
};
var summary = createDom('div', {className: 'summary'});
var summary = createDom('div', {className: 'jasmine-summary'});
var topResults = new j$.ResultsNode({}, '', null),
currentParent = topResults;
@@ -110,8 +110,12 @@ jasmineRequire.HtmlReporter = function(j$) {
specsExecuted++;
}
if (!symbols){
symbols = find('.jasmine-symbol-summary');
}
symbols.appendChild(createDom('li', {
className: noExpectations(result) ? 'empty' : result.status,
className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
id: 'spec_' + result.id,
title: result.fullName
}
@@ -121,18 +125,18 @@ jasmineRequire.HtmlReporter = function(j$) {
failureCount++;
var failure =
createDom('div', {className: 'spec-detail failed'},
createDom('div', {className: 'description'},
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
),
createDom('div', {className: 'messages'})
createDom('div', {className: 'jasmine-messages'})
);
var messages = failure.childNodes[1];
for (var i = 0; i < result.failedExpectations.length; i++) {
var expectation = result.failedExpectations[i];
messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack));
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
}
failures.push(failure);
@@ -143,57 +147,106 @@ jasmineRequire.HtmlReporter = function(j$) {
}
};
this.jasmineDone = function() {
var banner = find('.banner');
banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
this.jasmineDone = function(doneResult) {
var banner = find('.jasmine-banner');
var alert = find('.jasmine-alert');
var order = doneResult && doneResult.order;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
var alert = find('.alert');
banner.appendChild(
createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
createDom('div', { className: 'jasmine-exceptions' },
createDom('input', {
className: 'jasmine-raise',
id: 'jasmine-raise-exceptions',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
createDom('div', { className: 'jasmine-throw-failures' },
createDom('input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
createDom('div', { className: 'jasmine-random-order' },
createDom('input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
)
));
alert.appendChild(createDom('span', { className: 'exceptions' },
createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'),
createDom('input', {
className: 'raise',
id: 'raise-exceptions',
type: 'checkbox'
})
));
var checkbox = find('#raise-exceptions');
var raiseCheckbox = find('#jasmine-raise-exceptions');
checkbox.checked = !env.catchingExceptions();
checkbox.onclick = onRaiseExceptionsClick;
raiseCheckbox.checked = !env.catchingExceptions();
raiseCheckbox.onclick = onRaiseExceptionsClick;
var throwCheckbox = find('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.onclick = onThrowExpectationsClick;
var randomCheckbox = find('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.onclick = onRandomClick;
var optionsMenu = find('.jasmine-run-options'),
optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
if (specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
alert.appendChild(
createDom('span', {className: 'bar skipped'},
createDom('span', {className: 'jasmine-bar jasmine-skipped'},
createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
)
);
}
var statusBarMessage = '';
var statusBarClassName = 'bar ';
var statusBarClassName = 'jasmine-bar ';
if (totalSpecsDefined > 0) {
statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
statusBarClassName += (failureCount > 0) ? 'failed' : 'passed';
statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
} else {
statusBarClassName += 'skipped';
statusBarClassName += 'jasmine-skipped';
statusBarMessage += 'No specs found';
}
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
var seedBar;
if (order && order.random) {
seedBar = createDom('span', {className: 'jasmine-seed-bar'},
', randomized with seed ',
createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed)
);
}
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
for(i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
var errorBarClassName = 'bar errored';
var errorBarClassName = 'jasmine-bar jasmine-errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
}
}
var results = find('.results');
var results = find('.jasmine-results');
results.appendChild(summary);
summaryList(topResults, summary);
@@ -203,8 +256,8 @@ jasmineRequire.HtmlReporter = function(j$) {
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (resultNode.type == 'suite') {
var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'suite-detail'},
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'jasmine-suite-detail'},
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
@@ -213,8 +266,8 @@ jasmineRequire.HtmlReporter = function(j$) {
domParent.appendChild(suiteListNode);
}
if (resultNode.type == 'spec') {
if (domParent.getAttribute('class') != 'specs') {
specListNode = createDom('ul', {className: 'specs'});
if (domParent.getAttribute('class') != 'jasmine-specs') {
specListNode = createDom('ul', {className: 'jasmine-specs'});
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
@@ -226,7 +279,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
specListNode.appendChild(
createDom('li', {
className: resultNode.result.status,
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom('a', {href: specHref(resultNode.result)}, specDescription)
@@ -238,24 +291,24 @@ jasmineRequire.HtmlReporter = function(j$) {
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'menu bar spec-list'},
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
createDom('span', {}, 'Spec List | '),
createDom('a', {className: 'failures-menu', href: '#'}, 'Failures')));
createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures')));
alert.appendChild(
createDom('span', {className: 'menu bar failure-list'},
createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'),
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'},
createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'),
createDom('span', {}, ' | Failures ')));
find('.failures-menu').onclick = function() {
setMenuModeTo('failure-list');
find('.jasmine-failures-menu').onclick = function() {
setMenuModeTo('jasmine-failure-list');
};
find('.spec-list-menu').onclick = function() {
setMenuModeTo('spec-list');
find('.jasmine-spec-list-menu').onclick = function() {
setMenuModeTo('jasmine-spec-list');
};
setMenuModeTo('failure-list');
setMenuModeTo('jasmine-failure-list');
var failureNode = find('.failures');
var failureNode = find('.jasmine-failures');
for (var i = 0; i < failures.length; i++) {
failureNode.appendChild(failures[i]);
}
@@ -313,6 +366,10 @@ jasmineRequire.HtmlReporter = function(j$) {
return addToExistingQueryString('spec', result.fullName);
}
function seedHref(seed) {
return addToExistingQueryString('seed', seed);
}
function defaultQueryString(key, value) {
return '?' + key + '=' + value;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.2.1"
VERSION = "2.4.0"
end
end

View File

@@ -1,23 +1,34 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.2.1",
"version": "2.4.0",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"
},
"keywords": [
"test",
"jasmine",
"tdd",
"bdd"
],
"scripts": {
"test": "./node_modules/.bin/grunt jshint execSpecsInNode"
},
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
"homepage": "http://jasmine.github.io",
"main": "./lib/jasmine-core.js",
"devDependencies": {
"glob": "~5.0.13",
"grunt": "~0.4.1",
"grunt-contrib-jshint": "~0.7.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-cli": "^0.1.13",
"grunt-contrib-compass": "~0.6.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.7.0",
"jasmine": "git://github.com/jasmine/jasmine-npm.git",
"load-grunt-tasks": "^0.4.0",
"shelljs": "~0.1.4",
"glob": "~3.2.9",
"jasmine": "https://github.com/jasmine/jasmine-npm/archive/master.tar.gz",
"load-grunt-tasks": "^0.4.0"
"temp": "~0.8.1"
}
}

81
release_notes/2.3.0.md Normal file
View File

@@ -0,0 +1,81 @@
# Jasmine Core 2.3.0 Release Notes
## Changes
* Style disabled specs in the results list
* Use `onclick` directly to better support older webkit
* Don't use deprecated `onComplete` syntax for jasmine-npm
* Allow the clock to be installed for the duration of a single closure
* Add safari 7 & 8 to browser matrix
* Remove unused standaloneBuilder var from Gruntfile
* Add test script to package.json
* Update bower.json keywords to match package.json keywords
* Add keywords to package.json
* refuse to execute an order if it would cause a suite with a beforeAll or afterAll to be re-entered after leaving once
## Pull Requests & Issues
* Specify a main entry point for bower so it can be loaded easier
- Merges [#827](https://github.com/jasmine/jasmine/issues/827) from @davetron5000
* Use `instanceof` when checking Error types in toThrowError
- Fixes [#819](https://github.com/jasmine/jasmine/issues/819)
* Remove periods from bullet points for consistency with rest of document
- Merge [#818](https://github.com/jasmine/jasmine/issues/818) from @lpww
* Subjective readability improvements to CONTRIBUTING.md
- Merge [#815](https://github.com/jasmine/jasmine/issues/815) from @jhamon
* Don't install the clock if the current timing functions aren't the originals
- Fixes [#782](https://github.com/jasmine/jasmine/issues/782)
* Properly pass `j$` to `Any` so it can use other jasmine stuff
- Fixes [#806](https://github.com/jasmine/jasmine/issues/806)
* Correctly handle functions that are scheduled after the clock is uninstalled and reinstalled from within Clock#tick.
- Merges [#804](https://github.com/jasmine/jasmine/issues/804) from @sgravrock
- Fixes [#790](https://github.com/jasmine/jasmine/issues/790).
* Allow user to stop a specs execution when an expectation fails
- Fixes [#577](https://github.com/jasmine/jasmine/issues/577)
* Remove unnecessary conditional
- Merges [#788](https://github.com/jasmine/jasmine/issues/788) from @toddbranch
* Show the name of the constructor function when printing an `any` instead of a `toString` of the entire constructor
- Fixes [#796](https://github.com/jasmine/jasmine/issues/796)
* Don't use hardcoded temporary directory paths
- Merges [#789](https://github.com/jasmine/jasmine/issues/789) from sgravrock
* Execute beforeAll/afterAll once per suite instead of once per child when running focused specs/suites
- Fixes [#773](https://github.com/jasmine/jasmine/issues/773)
* Report children of an xdescribe similarly to how they would be reported if they were themselves x'd out
- Fixes [#774](https://github.com/jasmine/jasmine/issues/774)
- Fixes [#776](https://github.com/jasmine/jasmine/issues/776)
* Fixes issue where mock clock was being used by QueueRunner
- Fixes [#783](https://github.com/jasmine/jasmine/issues/783)
- Fixes [#792](https://github.com/jasmine/jasmine/issues/792)
* add missing semicolon
- Merges [#775](https://github.com/jasmine/jasmine/issues/775) from @joscha
* ObjectContaining matches prototype properties
- Fixes [#769](https://github.com/jasmine/jasmine/issues/769)
* Updates pretty printer to include array properties
- Fixes [#766](https://github.com/jasmine/jasmine/issues/766)
* Update year copyright
- Merges [#768](https://github.com/jasmine/jasmine/issues/768) from @danilovaz
* Allow arrays from different frames or contexts to be equal
- Merges [#767](https://github.com/jasmine/jasmine/issues/767) from @juliemr
- Fixes [#765](https://github.com/jasmine/jasmine/issues/765)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

14
release_notes/2.3.1.md Normal file
View File

@@ -0,0 +1,14 @@
# Jasmine 2.3.1 Release Notes
## Summary
This release is a packaging update for bower only.
## Pull Requests & Issues
* Point Bower's main field to jasmine.js, which is browser-friendly.
- Merge [#843](https://github.com/jasmine/jasmine/issues/843) from @evoL
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

14
release_notes/2.3.2.md Normal file
View File

@@ -0,0 +1,14 @@
# Jasmine 2.3.2 Release Notes
## Summary
This is a hotfix release to fix a regression with specs declared without a function body
## Pull Requests & Issues
* A spec without a function provided should be `pending` not `disabled`
- Fixes [#840](https://github.com/jasmine/jasmine/issues/840)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

14
release_notes/2.3.3.md Normal file
View File

@@ -0,0 +1,14 @@
# Jasmine 2.3.3 Release Notes
## Summary
This is a hotfix release to fix a regression with the execution context for `beforeAll`
## Pull Requests & Issues
* Set the shared user context correctly when executing the top level suite
- Fixes [#846](https://github.com/jasmine/jasmine/issues/846)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

22
release_notes/2.3.4.md Normal file
View File

@@ -0,0 +1,22 @@
# Jasmine 2.3.4 Release Notes
## Summary
This is a hotfix release to fix a regression with execution ordering
## Pull Requests & Issues
* Fix ordering for suites with more than 11 direct children.
- Fixes [#850](https://github.com/jasmine/jasmine/issues/850)
* Update standalone installation instructions to reference the releases page
- Fixes [#603](https://github.com/jasmine/jasmine/issues/603)
* Remove dead CSS class styles
- Merges [#849](https://github.com/jasmine/jasmine/issues/849) from @prather-mcs
- Merges [#848](https://github.com/jasmine/jasmine/issues/848) from @prather-mcs
- Fixes [#847](https://github.com/jasmine/jasmine/issues/847)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

91
release_notes/2.4.0.md Normal file
View File

@@ -0,0 +1,91 @@
# Jasmine Core 2.4.0 Release Notes
## Summary
This release contains a number of fixes and pull requests.
The most notable is probably that Jasmine now supports randomization of spec order
## Changes
* Run jasmine's specs in random order
* Add support for returning run details for reporting randomness
* Use className instead of class when creating DOM elements
## Pull Requests & Issues
* Syntax highlighting in README.md
- Merges [#973](https://github.com/jasmine/jasmine/issues/973) from @brunoqc
* Added a throw error block in describe incase a function with arguments is passed in describe
- Fixes [#896](https://github.com/jasmine/jasmine/issues/896)
- Merges [#955](https://github.com/jasmine/jasmine/issues/955) from @himajasuman
* Remove unused `queueableFn` arg from `onException`
- Fixes [#958](https://github.com/jasmine/jasmine/issues/958)
* Remove unused parameter from toThrowError
- Merges [#957](https://github.com/jasmine/jasmine/issues/957) from @FuzzySockets
* Abort spying when the target cannot be spied upon
- Fixes [#948](https://github.com/jasmine/jasmine/issues/948)
- Merges [#949](https://github.com/jasmine/jasmine/issues/949) from @StephanBijzitter
* Removed GOALS_2.0.md, doesn't seem to be needed anymore
- Merges [#954](https://github.com/jasmine/jasmine/issues/954) from @matthewhuff89
* Change #xit so that it will output a more BDD-style pending message
- Merges [#942](https://github.com/jasmine/jasmine/issues/942) from @lalunamel
- Fixes [#930](https://github.com/jasmine/jasmine/issues/930)
- Fixes [#912](https://github.com/jasmine/jasmine/issues/912)
* Allow tests to run in random order
- Merges [#927](https://github.com/jasmine/jasmine/issues/927) from @marcioj
* Use toString for objects if it has been overriden
- Merges [#929](https://github.com/jasmine/jasmine/issues/929) from @myitcv
- Fixes [#928](https://github.com/jasmine/jasmine/issues/928)
* Fix circles/x from getting cut off on Mac/chrome
- Merges [#932](https://github.com/jasmine/jasmine/issues/932) from @James-Dunn
* Postpone find() until it is needed
- Merges [#924](https://github.com/jasmine/jasmine/issues/924) from @danielalexiuc
- Fixes [#917](https://github.com/jasmine/jasmine/issues/917)
* check for global before assigning
* Reverse suite afterEach behavior to match semantics?
- Merges [#908](https://github.com/jasmine/jasmine/issues/908) from @mcamac
* Use badges from shields.io
- Merges [#902](https://github.com/jasmine/jasmine/issues/902) from @SimenB
* xdescribe marks pending, plus associated tests.
- Merges [#869](https://github.com/jasmine/jasmine/issues/869) from @ljwall
- Fixes [#855](https://github.com/jasmine/jasmine/issues/855)
* Update glob to latest
- Merge [#892](https://github.com/jasmine/jasmine/issues/892) from @obastemur
- Fixes [#891](https://github.com/jasmine/jasmine/issues/891)
* Remove moot `version` property from bower.json
- Merges [#874](https://github.com/jasmine/jasmine/issues/874) from @kkirsche
* add toHaveBeenCalledTimes matcher
- Merges [#871](https://github.com/jasmine/jasmine/issues/871) from @logankd
- Fixes [#853](https://github.com/jasmine/jasmine/issues/853)
* Update CONTRIBUTING.md
- Merges [#856](https://github.com/jasmine/jasmine/issues/856) from @lpww
* Make the HtmlReport CSS classes "unique enough"
- Merges [#851](https://github.com/jasmine/jasmine/issues/851) from @prather-mcs
- Fixes [#844](https://github.com/jasmine/jasmine/issues/844)
* Raise an error when jasmine.any() isn't passed a constructor
- Merges [#854](https://github.com/jasmine/jasmine/issues/854) from @danfinnie
- Fixes [#852](https://github.com/jasmine/jasmine/issues/852)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

View File

@@ -6,7 +6,7 @@ describe("Clock", function() {
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
fakeGlobal.setTimeout(delayedFn, 0);
@@ -28,7 +28,7 @@ describe("Clock", function() {
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
fakeGlobal.clearTimeout("foo");
@@ -50,7 +50,7 @@ describe("Clock", function() {
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
fakeGlobal.setInterval(delayedFn, 0);
@@ -72,7 +72,7 @@ describe("Clock", function() {
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
fakeGlobal.clearInterval("foo");
@@ -88,6 +88,78 @@ describe("Clock", function() {
expect(fakeClearInterval).not.toHaveBeenCalled();
});
it("does not install if the current setTimeout is not the original function on the global", function() {
var originalFakeSetTimeout = function() {},
replacedSetTimeout = function() {},
fakeGlobal = { setTimeout: originalFakeSetTimeout },
delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'),
mockDate = {},
clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate);
fakeGlobal.setTimeout = replacedSetTimeout;
expect(function() {
clock.install();
}).toThrowError(/unable to install/);
expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled();
expect(fakeGlobal.setTimeout).toBe(replacedSetTimeout);
});
it("does not install if the current clearTimeout is not the original function on the global", function() {
var originalFakeClearTimeout = function() {},
replacedClearTimeout = function() {},
fakeGlobal = { clearTimeout: originalFakeClearTimeout },
delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'),
mockDate = {},
clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate);
fakeGlobal.clearTimeout = replacedClearTimeout;
expect(function() {
clock.install();
}).toThrowError(/unable to install/);
expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled();
expect(fakeGlobal.clearTimeout).toBe(replacedClearTimeout);
});
it("does not install if the current setInterval is not the original function on the global", function() {
var originalFakeSetInterval = function() {},
replacedSetInterval = function() {},
fakeGlobal = { setInterval: originalFakeSetInterval },
delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'),
mockDate = {},
clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate);
fakeGlobal.setInterval = replacedSetInterval;
expect(function() {
clock.install();
}).toThrowError(/unable to install/);
expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled();
expect(fakeGlobal.setInterval).toBe(replacedSetInterval);
});
it("does not install if the current clearInterval is not the original function on the global", function() {
var originalFakeClearInterval = function() {},
replacedClearInterval = function() {},
fakeGlobal = { clearInterval: originalFakeClearInterval },
delayedFunctionSchedulerFactory = jasmine.createSpy('delayedFunctionSchedulerFactory'),
mockDate = {},
clock = new j$.Clock(fakeGlobal, delayedFunctionSchedulerFactory, mockDate);
fakeGlobal.clearInterval = replacedClearInterval;
expect(function() {
clock.install();
}).toThrowError(/unable to install/);
expect(delayedFunctionSchedulerFactory).not.toHaveBeenCalled();
expect(fakeGlobal.clearInterval).toBe(replacedClearInterval);
});
it("replaces the global timer functions on uninstall", function() {
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
fakeClearTimeout = jasmine.createSpy("global clearTimeout"),
@@ -102,7 +174,7 @@ describe("Clock", function() {
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction", "reset"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
clock.uninstall();
@@ -118,6 +190,103 @@ describe("Clock", function() {
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
});
it("can be installed for the duration of a passed in function and uninstalled when done", function() {
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
fakeClearTimeout = jasmine.createSpy("global clearTimeout"),
fakeSetInterval = jasmine.createSpy("global setInterval"),
fakeClearInterval = jasmine.createSpy("global clearInterval"),
fakeGlobal = {
setTimeout: fakeSetTimeout,
clearTimeout: fakeClearTimeout,
setInterval: fakeSetInterval,
clearInterval: fakeClearInterval
},
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction", "reset", "removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
passedFunctionCalled = false;
clock.withMock(function() {
fakeGlobal.setTimeout(delayedFn, 0);
fakeGlobal.clearTimeout("foo");
fakeGlobal.setInterval(delayedFn, 10);
fakeGlobal.clearInterval("bar");
passedFunctionCalled = true;
});
expect(passedFunctionCalled).toBe(true);
expect(fakeSetTimeout).not.toHaveBeenCalled();
expect(fakeClearTimeout).not.toHaveBeenCalled();
expect(fakeSetInterval).not.toHaveBeenCalled();
expect(fakeClearInterval).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalled();
delayedFunctionScheduler.scheduleFunction.calls.reset();
fakeGlobal.setTimeout(delayedFn, 0);
fakeGlobal.clearTimeout("foo");
fakeGlobal.setInterval(delayedFn, 10);
fakeGlobal.clearInterval("bar");
expect(fakeSetTimeout).toHaveBeenCalledWith(delayedFn, 0);
expect(fakeClearTimeout).toHaveBeenCalledWith("foo");
expect(fakeSetInterval).toHaveBeenCalledWith(delayedFn, 10);
expect(fakeClearInterval).toHaveBeenCalledWith("bar");
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
});
it("can be installed for the duration of a passed in function and uninstalled if an error is thrown", function() {
var fakeSetTimeout = jasmine.createSpy("global setTimeout"),
fakeClearTimeout = jasmine.createSpy("global clearTimeout"),
fakeSetInterval = jasmine.createSpy("global setInterval"),
fakeClearInterval = jasmine.createSpy("global clearInterval"),
fakeGlobal = {
setTimeout: fakeSetTimeout,
clearTimeout: fakeClearTimeout,
setInterval: fakeSetInterval,
clearInterval: fakeClearInterval
},
delayedFunctionScheduler = jasmine.createSpyObj("delayedFunctionScheduler", ["scheduleFunction", "reset", "removeFunctionWithId"]),
delayedFn = jasmine.createSpy("delayedFn"),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
passedFunctionCalled = false;
expect(function() {
clock.withMock(function() {
fakeGlobal.setTimeout(delayedFn, 0);
fakeGlobal.clearTimeout("foo");
fakeGlobal.setInterval(delayedFn, 10);
fakeGlobal.clearInterval("bar");
passedFunctionCalled = true;
throw 'oops';
});
}).toThrow('oops');
expect(passedFunctionCalled).toBe(true);
expect(fakeSetTimeout).not.toHaveBeenCalled();
expect(fakeClearTimeout).not.toHaveBeenCalled();
expect(fakeSetInterval).not.toHaveBeenCalled();
expect(fakeClearInterval).not.toHaveBeenCalled();
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalled();
delayedFunctionScheduler.scheduleFunction.calls.reset();
fakeGlobal.setTimeout(delayedFn, 0);
fakeGlobal.clearTimeout("foo");
fakeGlobal.setInterval(delayedFn, 10);
fakeGlobal.clearInterval("bar");
expect(fakeSetTimeout).toHaveBeenCalledWith(delayedFn, 0);
expect(fakeClearTimeout).toHaveBeenCalledWith("foo");
expect(fakeSetInterval).toHaveBeenCalledWith(delayedFn, 10);
expect(fakeClearInterval).toHaveBeenCalledWith("bar");
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
});
it("schedules the delayed function (via setTimeout) with the fake timer", function() {
var fakeSetTimeout = jasmine.createSpy('setTimeout'),
scheduleFunction = jasmine.createSpy('scheduleFunction'),
@@ -125,7 +294,7 @@ describe("Clock", function() {
fakeGlobal = { setTimeout: fakeSetTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
clock.setTimeout(delayedFn, 0, 'a', 'b');
@@ -142,7 +311,7 @@ describe("Clock", function() {
fakeGlobal = { setTimeout: fakeSetTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate),
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
timeoutId;
clock.install();
@@ -157,7 +326,7 @@ describe("Clock", function() {
fakeGlobal = { setTimeout: fakeClearTimeout },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
clock.clearTimeout(123);
@@ -173,7 +342,7 @@ describe("Clock", function() {
fakeGlobal = { setInterval: fakeSetInterval },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
clock.setInterval(delayedFn, 0, 'a', 'b');
@@ -190,7 +359,7 @@ describe("Clock", function() {
fakeGlobal = { setInterval: fakeSetInterval },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate),
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate),
intervalId;
clock.install();
@@ -205,7 +374,7 @@ describe("Clock", function() {
fakeGlobal = { setInterval: clearInterval },
delayedFn = jasmine.createSpy('delayedFn'),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
clock.clearInterval(123);
@@ -232,7 +401,7 @@ describe("Clock", function() {
setInterval: fakeSetInterval
},
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock(fakeGlobal, delayedFunctionScheduler, mockDate);
clock = new j$.Clock(fakeGlobal, function () { return delayedFunctionScheduler; }, mockDate);
fakeSetTimeout.apply = null;
fakeSetInterval.apply = null;
@@ -251,7 +420,6 @@ describe("Clock", function() {
clock.setInterval(fn, 0, 'extra');
}).toThrow();
});
});
describe("Clock (acceptance)", function() {
@@ -262,7 +430,7 @@ describe("Clock (acceptance)", function() {
recurring1 = jasmine.createSpy('recurring1'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: setTimeout}, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
@@ -309,7 +477,7 @@ describe("Clock (acceptance)", function() {
var clearedFn = jasmine.createSpy('clearedFn'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate),
clock = new j$.Clock({setTimeout: function() {}}, function () { return delayedFunctionScheduler; }, mockDate),
timeoutId;
clock.install();
@@ -327,7 +495,7 @@ describe("Clock (acceptance)", function() {
var spy = jasmine.createSpy('spy'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setInterval: function() {}}, delayedFunctionScheduler, mockDate),
clock = new j$.Clock({setInterval: function() {}}, function () { return delayedFunctionScheduler; }, mockDate),
intervalId;
clock.install();
@@ -345,7 +513,7 @@ describe("Clock (acceptance)", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: function() {}}, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
@@ -362,7 +530,7 @@ describe("Clock (acceptance)", function() {
delayedFn2 = jasmine.createSpy('delayedFn2'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: function() {}}, function () { return delayedFunctionScheduler; }, mockDate);
delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 0); });
clock.install();
@@ -381,7 +549,7 @@ describe("Clock (acceptance)", function() {
delayedFn2 = jasmine.createSpy('delayedFn2'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: function() {}}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: function() {}}, function () { return delayedFunctionScheduler; }, mockDate);
delayedFn1.and.callFake(function() { clock.setTimeout(delayedFn2, 1); });
clock.install();
@@ -392,11 +560,35 @@ describe("Clock (acceptance)", function() {
expect(delayedFn2).toHaveBeenCalled();
});
it("correctly schedules functions scheduled while the Clock is advancing but after the Clock is uninstalled", function() {
var delayedFn1 = jasmine.createSpy('delayedFn1'),
delayedFn2 = jasmine.createSpy('delayedFn2'),
delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
mockDate = { install: function() {}, tick: function() {}, uninstall: function() {} },
clock = new j$.Clock({setTimeout: function() {}}, function () { return delayedFunctionScheduler; }, mockDate);
delayedFn1.and.callFake(function() {
clock.uninstall();
clock.install();
clock.setTimeout(delayedFn2, 0);
});
clock.install();
clock.setTimeout(delayedFn1, 1);
clock.tick(1);
expect(delayedFn1).toHaveBeenCalled();
expect(delayedFn2).not.toHaveBeenCalled();
clock.tick(1);
expect(delayedFn2).toHaveBeenCalled();
});
it("does not mock the Date object by default", function() {
var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
global = {Date: Date},
mockDate = new j$.MockDate(global),
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: setTimeout}, function () { return delayedFunctionScheduler; }, mockDate);
clock.install();
@@ -413,7 +605,7 @@ describe("Clock (acceptance)", function() {
var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
global = {Date: Date},
mockDate = new j$.MockDate(global),
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate);
clock = new j$.Clock({setTimeout: setTimeout}, function () { return delayedFunctionScheduler; }, mockDate);
clock.install().mockDate();
@@ -437,7 +629,7 @@ describe("Clock (acceptance)", function() {
var delayedFunctionScheduler = new j$.DelayedFunctionScheduler(),
global = {Date: Date},
mockDate = new j$.MockDate(global),
clock = new j$.Clock({setTimeout: setTimeout}, delayedFunctionScheduler, mockDate),
clock = new j$.Clock({setTimeout: setTimeout}, function () { return delayedFunctionScheduler; }, mockDate),
baseTime = new Date(2013, 9, 23);

View File

@@ -113,47 +113,6 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).not.toHaveBeenCalled();
});
it("reset removes scheduled functions", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
scheduler.scheduleFunction(fn, 0);
expect(fn).not.toHaveBeenCalled();
scheduler.reset();
scheduler.tick(0);
expect(fn).not.toHaveBeenCalled();
});
it("reset resets the returned ids", function() {
var scheduler = new j$.DelayedFunctionScheduler();
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
scheduler.reset();
expect(scheduler.scheduleFunction(function() { }, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() { }, 0, [], false, 123)).toBe(123);
});
it("reset resets the current tick time", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
expect(fn).not.toHaveBeenCalled();
scheduler.tick(15);
scheduler.reset();
scheduler.scheduleFunction(fn, 20, [], false, 1, 20);
scheduler.tick(5);
expect(fn).not.toHaveBeenCalled();
});
it("executes recurring functions interleaved with regular functions in the correct order", function() {
var scheduler = new j$.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),

View File

@@ -25,4 +25,44 @@ describe("Env", function() {
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
});
});
describe('#describe', function () {
var spec = function(done){};
it("throws the error", function() {
expect(function() {
env.describe('done method', spec);
}).toThrow(new Error('describe does not expect a done parameter'));
});
});
it('can configure specs to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
spyOn(j$, 'Spec');
env.it('foo', function() {});
expect(j$.Spec).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: true
}));
});
it('can configure suites to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
spyOn(j$, 'Suite');
env.describe('foo', function() {});
expect(j$.Suite).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: true
}));
});
describe('#xit', function() {
it('calls spec.pend with "Temporarily disabled with xit"', function() {
var pendSpy = jasmine.createSpy();
spyOn(env, 'it').and.returnValue({
pend: pendSpy
});
env.xit();
expect(pendSpy).toHaveBeenCalledWith('Temporarily disabled with xit');
});
});
});

View File

@@ -248,4 +248,12 @@ describe("JsApiReporter", function() {
});
});
});
describe('#runDetails', function() {
it('should have details about the run', function() {
var reporter = new j$.JsApiReporter({});
reporter.jasmineDone({some: {run: 'details'}});
expect(reporter.runDetails).toEqual({some: {run: 'details'}});
});
});
});

View File

@@ -14,21 +14,63 @@ describe("j$.pp", function () {
expect(j$.pp(-0)).toEqual("-0");
});
it("should stringify arrays properly", function() {
expect(j$.pp([1, 2])).toEqual("[ 1, 2 ]");
expect(j$.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', Object({ }), undefined, null ]");
});
describe('stringify arrays', function() {
it("should stringify arrays properly", function() {
expect(j$.pp([1, 2])).toEqual("[ 1, 2 ]");
expect(j$.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', Object({ }), undefined, null ]");
});
it("should indicate circular array references", function() {
var array1 = [1, 2];
var array2 = [array1];
array1.push(array2);
expect(j$.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
});
it("should truncate arrays that are longer than j$.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
var originalMaxLength = j$.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var array = [1, 2, 3];
it("should not indicate circular references incorrectly", function() {
var array = [ [1] ];
expect(j$.pp(array)).toEqual("[ [ 1 ] ]");
try {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(j$.pp(array)).toEqual("[ 1, 2, ... ]");
} finally {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
});
it("should stringify arrays with properties properly", function() {
var arr = [1, 2];
arr.foo = 'bar';
arr.baz = {};
expect(j$.pp(arr)).toEqual("[ 1, 2, foo: 'bar', baz: Object({ }) ]");
});
it("should stringify empty arrays with properties properly", function() {
var empty = [];
empty.foo = 'bar';
empty.baz = {};
expect(j$.pp(empty)).toEqual("[ foo: 'bar', baz: Object({ }) ]");
});
it("should stringify long arrays with properties properly", function() {
var originalMaxLength = j$.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var long = [1,2,3];
long.foo = 'bar';
long.baz = {};
try {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(j$.pp(long)).toEqual("[ 1, 2, ..., foo: 'bar', baz: Object({ }) ]");
} finally {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
});
it("should indicate circular array references", function() {
var array1 = [1, 2];
var array2 = [array1];
array1.push(array2);
expect(j$.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
});
it("should not indicate circular references incorrectly", function() {
var array = [ [1] ];
expect(j$.pp(array)).toEqual("[ [ 1 ] ]");
});
});
it("should stringify objects properly", function() {
@@ -77,18 +119,6 @@ describe("j$.pp", function () {
}
});
it("should truncate arrays that are longer than j$.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
var originalMaxLength = j$.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var array = [1, 2, 3];
try {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(j$.pp(array)).toEqual("[ 1, 2, ... ]");
} finally {
j$.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
});
it("should stringify RegExp objects properly", function() {
expect(j$.pp(/x|y|z/)).toEqual("/x|y|z/");
});
@@ -151,6 +181,14 @@ describe("j$.pp", function () {
expect(j$.pp(obj)).toEqual("strung");
});
it("should stringify objects that implement custom toString", function () {
var obj = {
toString: function () { return "my toString"; }
};
expect(j$.pp(obj)).toEqual("my toString");
});
it("should handle objects with null prototype", function() {
if (jasmine.getEnv().ieVersion < 9) { return; }

View File

@@ -119,7 +119,6 @@ describe("Spec", function() {
queueRunnerFactory: fakeQueueRunner
});
expect(spec.status()).toBe('pending');
});
@@ -148,6 +147,29 @@ describe("Spec", function() {
expect(resultCallback).toHaveBeenCalled();
});
it("can be disabled at execution time by a parent", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
onStart:startCallback,
queueableFn: { fn: specBody },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
spec.execute(undefined, false);
expect(spec.result.status).toBe('disabled');
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(specBody).not.toHaveBeenCalled();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalled();
});
it("can be marked pending, but still calls callbacks when executed", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
@@ -232,6 +254,40 @@ describe("Spec", function() {
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['expectation2']);
});
it("throws an ExpectationFailed error upon receiving a failed expectation when 'throwOnExpectationFailure' is set", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
spec.addExpectationResult(true, 'passed');
expect(function() {
spec.addExpectationResult(false, 'failed')
}).toThrowError(j$.errors.ExpectationFailed);
spec.execute();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['passed']);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['failed']);
});
it("does not throw an ExpectationFailed error when handling an error", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
spec.onException('failing exception');
});
it("can return its full name", function() {
var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val');
@@ -244,7 +300,7 @@ describe("Spec", function() {
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
});
describe("when a spec is marked pending during execution", function() {
describe("when a spec is marked pending during execution", function() {
it("should mark the spec as pending", function() {
var fakeQueueRunner = function(opts) {
opts.onException(new Error(j$.Spec.pendingSpecExceptionMessage));
@@ -279,4 +335,86 @@ describe("Spec", function() {
expect(spec.result.pendingReason).toEqual('custom message');
});
});
it("should log a failure when handling an exception", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback
});
spec.onException('foo');
spec.execute();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([{
error: 'foo',
matcherName: '',
passed: false,
expected: '',
actual: ''
}]);
});
it("should not log an additional failure when handling an ExpectationFailed error", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
spec = new j$.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback
});
spec.onException(new j$.errors.ExpectationFailed());
spec.execute();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([]);
});
it("retrieves a result with updated status", function() {
var spec = new j$.Spec({ queueableFn: { fn: function() {} } });
expect(spec.getResult().status).toBe('passed');
});
it("retrives a result with disabled status", function() {
var spec = new j$.Spec({ queueableFn: { fn: function() {} } });
spec.disable();
expect(spec.getResult().status).toBe('disabled');
});
it("retrives a result with pending status", function() {
var spec = new j$.Spec({ queueableFn: { fn: function() {} } });
spec.pend();
expect(spec.getResult().status).toBe('pending');
});
it("should not be executable when disabled", function() {
var spec = new j$.Spec({
queueableFn: { fn: function() {} }
});
spec.disable();
expect(spec.isExecutable()).toBe(false);
});
it("should be executable when pending", function() {
var spec = new j$.Spec({
queueableFn: { fn: function() {} }
});
spec.pend();
expect(spec.isExecutable()).toBe(true);
});
it("should be executable when not disabled or pending", function() {
var spec = new j$.Spec({
queueableFn: { fn: function() {} }
});
expect(spec.isExecutable()).toBe(true);
});
});

View File

@@ -37,6 +37,35 @@ describe("SpyRegistry", function() {
}).toThrowError(/has already been spied upon/);
});
it("checks if it can be spied upon", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var scope = {};
function myFunc() {
return 1;
}
Object.defineProperty(scope, 'myFunc', {
get: function() {
return myFunc;
}
});
var spies = [],
spyRegistry = new j$.SpyRegistry({currentSpies: function() { return spies; }}),
subject = { spiedFunc: scope.myFunc };
expect(function() {
spyRegistry.spyOn(scope, 'myFunc');
}).toThrowError(/is not declared writable or has no setter/);
expect(function() {
spyRegistry.spyOn(subject, 'spiedFunc');
}).not.toThrowError(/is not declared writable or has no setter/);
});
it("overrides the method on the object and returns the spy", function() {
var originalFunctionWasCalled = false,
spyRegistry = new j$.SpyRegistry(),

View File

@@ -52,31 +52,6 @@ describe("Suite", function() {
expect(suite.beforeFns).toEqual([innerBefore, outerBefore]);
});
it("runs beforeAll functions in order of needed execution", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunner
}),
firstBefore = jasmine.createSpy('outerBeforeAll'),
lastBefore = jasmine.createSpy('insideBeforeAll'),
fakeIt = {execute: jasmine.createSpy('it'), isExecutable: function() { return true; } };
suite.beforeAll(firstBefore);
suite.beforeAll(lastBefore);
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[0]();
expect(firstBefore).toHaveBeenCalled();
suiteFns[1]();
expect(lastBefore).toHaveBeenCalled();
});
it("adds after functions in order of needed execution", function() {
var env = new j$.Env(),
suite = new j$.Suite({
@@ -92,244 +67,6 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it("runs afterAll functions in order of needed execution", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunner
}),
firstAfter = jasmine.createSpy('outerAfterAll'),
lastAfter = jasmine.createSpy('insideAfterAll'),
fakeIt = {execute: jasmine.createSpy('it'), isExecutable: function() { return true; } };
suite.afterAll(firstAfter);
suite.afterAll(lastAfter);
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
suiteFns[1]();
expect(firstAfter).toHaveBeenCalled();
suiteFns[2]();
expect(lastAfter).toHaveBeenCalled();
});
it("does not run *All functions if runnables are explicitly set", function(){
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunner,
runnablesExplictlySetGetter: function(){return true;}
}),
beforeAll = jasmine.createSpy('beforeAll'),
afterAll = jasmine.createSpy('afterAll'),
fakeIt = {execute: jasmine.createSpy('it'), isExecutable: function() { return true; } };
suite.beforeAll(beforeAll);
suite.afterAll(afterAll);
suite.addChild(fakeIt);
suite.execute();
var suiteFns = fakeQueueRunner.calls.mostRecent().args[0].queueableFns;
expect(suite.isExecutable()).toBeFalsy();
expect(suiteFns.length).toEqual(1);
expect(beforeAll).not.toHaveBeenCalled();
expect(afterAll).not.toHaveBeenCalled();
});
it("can be disabled, but still calls callbacks", function() {
var env = new j$.Env(),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
onStart = jasmine.createSpy('onStart'),
resultCallback = jasmine.createSpy('resultCallback'),
onComplete = jasmine.createSpy('onComplete'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
onStart: onStart,
resultCallback: resultCallback,
queueRunner: fakeQueueRunner
});
suite.disable();
expect(suite.disabled).toBe(true);
suite.execute(onComplete);
expect(fakeQueueRunner).not.toHaveBeenCalled();
expect(onStart).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalled();
});
it("delegates execution of its specs, suites, beforeAlls, and afterAlls", function() {
var env = new j$.Env(),
parentSuiteDone = jasmine.createSpy('parent suite done'),
fakeQueueRunnerForParent = jasmine.createSpy('fake parent queue runner'),
parentSuite = new j$.Suite({
env: env,
description: "I am a parent suite",
queueRunner: fakeQueueRunnerForParent
}),
fakeQueueRunner = jasmine.createSpy('fake queue runner'),
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1'),
isExecutable: function() { return true; }
},
beforeAllFn = { fn: jasmine.createSpy('beforeAll') },
afterAllFn = { fn: jasmine.createSpy('afterAll') };
spyOn(suite, "execute");
parentSuite.addChild(fakeSpec1);
parentSuite.addChild(suite);
parentSuite.beforeAll(beforeAllFn);
parentSuite.afterAll(afterAllFn);
parentSuite.execute(parentSuiteDone);
var parentSuiteFns = fakeQueueRunnerForParent.calls.mostRecent().args[0].queueableFns;
parentSuiteFns[0].fn();
expect(beforeAllFn.fn).toHaveBeenCalled();
parentSuiteFns[1].fn();
expect(fakeSpec1.execute).toHaveBeenCalled();
parentSuiteFns[2].fn();
expect(suite.execute).toHaveBeenCalled();
parentSuiteFns[3].fn();
expect(afterAllFn.fn).toHaveBeenCalled();
});
it("does not run beforeAll or afterAll if there are no executable child specs", function() {
var env = new j$.Env(),
fakeQueueRunnerForParent = jasmine.createSpy('fake parent queue runner'),
fakeQueueRunnerForChild = jasmine.createSpy('fake child queue runner'),
parentSuite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunnerForParent
}),
childSuite = new j$.Suite({
env: env,
description: "I am a suite",
queueRunner: fakeQueueRunnerForChild,
parentSuite: parentSuite
}),
beforeAllFn = jasmine.createSpy('beforeAll'),
afterAllFn = jasmine.createSpy('afterAll');
parentSuite.addChild(childSuite);
parentSuite.beforeAll(beforeAllFn);
parentSuite.afterAll(afterAllFn);
parentSuite.execute();
expect(fakeQueueRunnerForParent).toHaveBeenCalledWith(jasmine.objectContaining({
queueableFns: [{ fn: jasmine.any(Function) }]
}));
});
it("calls a provided onStart callback when starting", function() {
var env = new j$.Env(),
suiteStarted = jasmine.createSpy('suiteStarted'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
onStart: suiteStarted,
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1'),
isExecutable: function() { return true; }
};
suite.execute();
expect(suiteStarted).toHaveBeenCalledWith(suite);
});
it("calls a provided onComplete callback when done", function() {
var env = new j$.Env(),
suiteCompleted = jasmine.createSpy('parent suite done'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute(suiteCompleted);
expect(suiteCompleted).toHaveBeenCalled();
});
it("calls a provided result callback when done", function() {
var env = new j$.Env(),
suiteResultsCallback = jasmine.createSpy('suite result callback'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner,
resultCallback: suiteResultsCallback
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.execute();
expect(suiteResultsCallback).toHaveBeenCalledWith({
id: suite.id,
status: 'finished',
description: "with a child suite",
fullName: "with a child suite",
failedExpectations: []
});
});
it("calls a provided result callback with status being disabled when disabled and done", function() {
var env = new j$.Env(),
suiteResultsCallback = jasmine.createSpy('suite result callback'),
fakeQueueRunner = function(attrs) { attrs.onComplete(); },
suite = new j$.Suite({
env: env,
description: "with a child suite",
queueRunner: fakeQueueRunner,
resultCallback: suiteResultsCallback
}),
fakeSpec1 = {
execute: jasmine.createSpy('fakeSpec1')
};
suite.disable();
suite.execute();
expect(suiteResultsCallback).toHaveBeenCalledWith({
id: suite.id,
status: 'disabled',
description: "with a child suite",
fullName: "with a child suite",
failedExpectations: []
});
});
it('has a status of failed if any afterAll expectations have failed', function() {
var suite = new j$.Suite({
expectationResultFactory: function() { return 'hi'; }
@@ -339,4 +76,85 @@ describe("Suite", function() {
suite.addExpectationResult(false);
expect(suite.status()).toBe('failed');
});
it("retrieves a result with updated status", function() {
var suite = new j$.Suite({});
expect(suite.getResult().status).toBe('finished');
});
it("retrieves a result with disabled status", function() {
var suite = new j$.Suite({});
suite.disable();
expect(suite.getResult().status).toBe('disabled');
});
it("retrieves a result with pending status", function() {
var suite = new j$.Suite({});
suite.pend();
expect(suite.getResult().status).toBe('pending');
});
it("priviledges a disabled status over pending status", function() {
var suite = new j$.Suite({});
suite.disable();
suite.pend();
expect(suite.getResult().status).toBe('disabled');
});
it("is executable if not disabled", function() {
var suite = new j$.Suite({});
expect(suite.isExecutable()).toBe(true);
});
it("is not executable if disabled", function() {
var suite = new j$.Suite({});
suite.disable();
expect(suite.isExecutable()).toBe(false);
});
it("tells all children about expectation failures, even if one throws", function() {
var suite = new j$.Suite({}),
child1 = { addExpectationResult: jasmine.createSpy('child1#expectationResult'), result: {} },
child2 = { addExpectationResult: jasmine.createSpy('child2#expectationResult'), result: {} };
suite.addChild(child1);
suite.addChild(child2);
child1.addExpectationResult.and.throwError('foo');
suite.addExpectationResult('stuff');
expect(child1.addExpectationResult).toHaveBeenCalledWith('stuff');
expect(child2.addExpectationResult).toHaveBeenCalledWith('stuff');
});
it("throws an ExpectationFailed when receiving a failed expectation in an afterAll when throwOnExpectationFailure is set", function() {
var suite = new j$.Suite({
expectationResultFactory: function(data) { return data; },
throwOnExpectationFailure: true
});
suite.addChild({ result: { status: 'done' } });
expect(function() {
suite.addExpectationResult(false, 'failed');
}).toThrowError(j$.errors.ExpectationFailed);
expect(suite.status()).toBe('failed');
expect(suite.result.failedExpectations).toEqual(['failed']);
});
it("does not add an additional failure when an expectation fails in an afterAll", function(){
var suite = new j$.Suite({});
suite.addChild({ result: { status: 'done' } });
suite.onException(new j$.errors.ExpectationFailed());
expect(suite.getResult().failedExpectations).toEqual([]);
})
});

View File

@@ -0,0 +1,756 @@
describe("TreeProcessor", function() {
var nodeNumber = 0, leafNumber = 0;
function Node(attrs) {
attrs = attrs || {};
this.id = 'node' + nodeNumber++;
this.children = attrs.children || [];
this.canBeReentered = function() {
return !attrs.noReenter;
};
this.isExecutable = function() {
return attrs.executable !== false;
};
this.sharedUserContext = function() {
return attrs.userContext || {};
};
this.getResult = jasmine.createSpy(this.id + '#execute');
this.beforeAllFns = attrs.beforeAllFns || [];
this.afterAllFns = attrs.afterAllFns || [];
}
function Leaf(attrs) {
attrs = attrs || {};
this.id = 'leaf' + leafNumber++;
this.isExecutable = function() {
return attrs.executable !== false;
};
this.execute = jasmine.createSpy(this.id + '#execute');
}
it("processes a single executable leaf", function() {
var leaf = new Leaf(),
processor = new j$.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
});
it("processes a single non-executable leaf", function() {
var leaf = new Leaf({ executable: false }),
processor = new j$.TreeProcessor({ tree: leaf, runnableIds: [leaf.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
});
it("processes a single non-specified leaf", function() {
var leaf = new Leaf(),
processor = new j$.TreeProcessor({ tree: leaf, runnableIds: [] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[leaf.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
});
it("processes a tree with a single leaf with the root specified", function() {
var leaf = new Leaf(),
parent = new Node({ children: [leaf] }),
processor = new j$.TreeProcessor({ tree: parent, runnableIds: [parent.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
expect(result[leaf.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
});
it("processes a tree with a single non-executable leaf, with the root specified", function() {
var leaf = new Leaf({ executable: false }),
parent = new Node({ children: [leaf] }),
processor = new j$.TreeProcessor({ tree: parent, runnableIds: [parent.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[parent.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
expect(result[leaf.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
});
it("processes a complicated tree with the root specified", function() {
var nonExecutable = new Leaf({ executable: false }),
executable = new Leaf({ executable: true }),
parent = new Node({ children: [nonExecutable, executable] }),
childless = new Node(),
childOfDisabled = new Leaf({ executable: true }),
disabledNode = new Node({ executable: false, children: [childOfDisabled] }),
root = new Node({ children: [parent, childless, disabledNode] }),
processor = new j$.TreeProcessor({ tree: root, runnableIds: [root.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
expect(result[root.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
expect(result[childless.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
expect(result[nonExecutable.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
expect(result[executable.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
expect(result[parent.id]).toEqual({
executable: true,
segments: jasmine.any(Array)
});
expect(result[disabledNode.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
expect(result[childOfDisabled.id]).toEqual({
executable: false,
segments: jasmine.any(Array)
});
});
it("marks the run order invalid if it would re-enter a node that does not allow re-entry", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
reentered = new Node({ noReenter: true, children: [leaf1, leaf2] }),
root = new Node({ children: [reentered, leaf3] }),
processor = new j$.TreeProcessor({ tree: root, runnableIds: [leaf1.id, leaf3.id, leaf2.id] }),
result = processor.processTree();
expect(result).toEqual({ valid: false });
});
it("marks the run order valid if a node being re-entered allows re-entry", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
reentered = new Node({ children: [leaf1, leaf2] }),
root = new Node({ children: [reentered, leaf3] }),
processor = new j$.TreeProcessor({ tree: root, runnableIds: [leaf1.id, leaf3.id, leaf2.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
});
it("marks the run order valid if a node which can't be re-entered is only entered once", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
noReentry = new Node({ noReenter: true }),
root = new Node({ children: [noReentry] }),
processor = new j$.TreeProcessor({ tree: root, runnableIds: [leaf2.id, leaf1.id, leaf3.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
});
it("marks the run order valid if a node which can't be re-entered is run directly", function() {
var leaf1 = new Leaf(),
noReentry = new Node({ noReenter: true }),
root = new Node({ children: [noReentry] }),
processor = new j$.TreeProcessor({ tree: root, runnableIds: [root.id] }),
result = processor.processTree();
expect(result.valid).toBe(true);
});
it("runs a single leaf", function() {
var leaf = new Leaf(),
node = new Node({ children: [leaf], userContext: { root: 'context' } }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({ tree: node, runnableIds: [leaf.id], queueRunnerFactory: queueRunner }),
treeComplete = jasmine.createSpy('treeComplete');
processor.execute(treeComplete);
expect(queueRunner).toHaveBeenCalledWith({
onComplete: treeComplete,
onException: jasmine.any(Function),
userContext: { root: 'context' },
queueableFns: [{ fn: jasmine.any(Function) }]
});
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn('foo');
expect(leaf.execute).toHaveBeenCalledWith('foo', true);
});
it("runs a node with no children", function() {
var node = new Node({ userContext: { node: 'context' } }),
root = new Node({ children: [node], userContext: { root: 'context' } }),
nodeStart = jasmine.createSpy('nodeStart'),
nodeComplete = jasmine.createSpy('nodeComplete'),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
nodeStart: nodeStart,
nodeComplete: nodeComplete,
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
expect(queueRunner).toHaveBeenCalledWith({
onComplete: treeComplete,
onException: jasmine.any(Function),
userContext: { root: 'context' },
queueableFns: [{ fn: jasmine.any(Function) }]
});
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn(nodeDone);
expect(nodeStart).toHaveBeenCalledWith(node);
expect(queueRunner).toHaveBeenCalledWith({
onComplete: jasmine.any(Function),
queueableFns: [],
userContext: { node: 'context' },
onException: jasmine.any(Function)
});
node.getResult.and.returnValue({ my: 'result' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { my: 'result' });
expect(nodeDone).toHaveBeenCalled();
});
it("runs a node with children", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
node = new Node({ children: [leaf1, leaf2] }),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(2);
queueableFns[0].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', true);
queueableFns[1].fn('bar');
expect(leaf2.execute).toHaveBeenCalledWith('bar', true);
});
it("runs a disabled node", function() {
var leaf1 = new Leaf(),
node = new Node({ children: [leaf1], executable: false }),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
nodeStart = jasmine.createSpy('nodeStart'),
nodeComplete = jasmine.createSpy('nodeComplete'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner,
nodeStart: nodeStart,
nodeComplete: nodeComplete
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
expect(nodeStart).toHaveBeenCalledWith(node);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(1);
queueableFns[0].fn('foo');
expect(leaf1.execute).toHaveBeenCalledWith('foo', false);
node.getResult.and.returnValue({ im: 'disabled' });
queueRunner.calls.mostRecent().args[0].onComplete();
expect(nodeComplete).toHaveBeenCalledWith(node, { im: 'disabled' });
});
it("runs beforeAlls for a node with children", function() {
var leaf = new Leaf(),
node = new Node({
children: [leaf],
beforeAllFns: ['beforeAll1', 'beforeAll2']
}),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual(['beforeAll1', 'beforeAll2', { fn: jasmine.any(Function) }]);
});
it("runs afterAlls for a node with children", function() {
var leaf = new Leaf(),
node = new Node({
children: [leaf],
afterAllFns: ['afterAll1', 'afterAll2']
}),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }, 'afterAll1', 'afterAll2']);
});
it("does not run beforeAlls or afterAlls for a node with no children", function() {
var node = new Node({
beforeAllFns: ['before'],
afterAllFns: ['after']
}),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([]);
});
it("does not run beforeAlls or afterAlls for a disabled node", function() {
var leaf = new Leaf(),
node = new Node({
children: [leaf],
beforeAllFns: ['before'],
afterAllFns: ['after'],
executable: false
}),
root = new Node({ children: [node] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [node.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete'),
nodeDone = jasmine.createSpy('nodeDone');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn(nodeDone);
queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns).toEqual([{ fn: jasmine.any(Function) }]);
});
it("runs leaves in the order specified", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
root = new Node({ children: [leaf1, leaf2] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [leaf2.id, leaf1.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn();
expect(leaf1.execute).not.toHaveBeenCalled();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(leaf1.execute).toHaveBeenCalled();
});
it("runs specified leaves before non-specified leaves", function() {
var specified = new Leaf(),
nonSpecified = new Leaf(),
root = new Node({ children: [nonSpecified, specified] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [specified.id],
queueRunnerFactory: queueRunner
}),
treeComplete = jasmine.createSpy('treeComplete');
processor.execute(treeComplete);
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn();
expect(nonSpecified.execute).not.toHaveBeenCalled();
expect(specified.execute).toHaveBeenCalledWith(undefined, true);
queueableFns[1].fn();
expect(nonSpecified.execute).toHaveBeenCalledWith(undefined, false);
});
it("runs nodes and leaves with a specified order", function() {
var specifiedLeaf = new Leaf(),
childLeaf = new Leaf(),
specifiedNode = new Node({ children: [childLeaf] }),
root = new Node({ children: [specifiedLeaf, specifiedNode] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [specifiedNode.id, specifiedLeaf.id],
queueRunnerFactory: queueRunner
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
queueableFns[0].fn();
expect(specifiedLeaf.execute).not.toHaveBeenCalled();
var nodeQueueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
nodeQueueableFns[0].fn();
expect(childLeaf.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(specifiedLeaf.execute).toHaveBeenCalled();
});
it("runs a node multiple times if the order specified leaves and re-enters it", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
leaf4 = new Leaf(),
leaf5 = new Leaf(),
reentered = new Node({ children: [leaf1, leaf2, leaf3] }),
root = new Node({ children: [reentered, leaf4, leaf5] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [leaf1.id, leaf4.id, leaf2.id, leaf5.id, leaf3.id],
queueRunnerFactory: queueRunner
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(5);
queueableFns[0].fn();
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(leaf4.execute).toHaveBeenCalled();
queueableFns[2].fn();
expect(queueRunner.calls.count()).toBe(3);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[3].fn();
expect(leaf5.execute).toHaveBeenCalled();
queueableFns[4].fn();
expect(queueRunner.calls.count()).toBe(4);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
it("runs a parent of a node with segments correctly", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
leaf4 = new Leaf(),
leaf5 = new Leaf(),
parent = new Node({ children: [leaf1, leaf2, leaf3] }),
grandparent = new Node({ children: [parent] }),
root = new Node({ children: [grandparent, leaf4, leaf5] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [leaf1.id, leaf4.id, leaf2.id, leaf5.id, leaf3.id],
queueRunnerFactory: queueRunner
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(5);
queueableFns[0].fn();
expect(queueRunner.calls.count()).toBe(2);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.count()).toBe(3);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(leaf4.execute).toHaveBeenCalled();
queueableFns[2].fn();
expect(queueRunner.calls.count()).toBe(4);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.count()).toBe(5);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[3].fn();
expect(leaf5.execute).toHaveBeenCalled();
queueableFns[4].fn();
expect(queueRunner.calls.count()).toBe(6);
expect(queueRunner.calls.mostRecent().args[0].queueableFns.length).toBe(1);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(queueRunner.calls.count()).toBe(7);
queueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
it("runs nodes in the order they were declared", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
parent = new Node({ children: [leaf2, leaf3] }),
root = new Node({ children: [leaf1, parent] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [root.id],
queueRunnerFactory: queueRunner
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(2);
queueableFns[0].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
var childFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(childFns.length).toBe(2);
childFns[0].fn();
expect(leaf2.execute).toHaveBeenCalled();
childFns[1].fn();
expect(leaf3.execute).toHaveBeenCalled();
});
it("runs large segments of nodes in the order they were declared", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
leaf4 = new Leaf(),
leaf5 = new Leaf(),
leaf6 = new Leaf(),
leaf7 = new Leaf(),
leaf8 = new Leaf(),
leaf9 = new Leaf(),
leaf10 = new Leaf(),
leaf11 = new Leaf(),
root = new Node({ children: [leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, leaf8, leaf9, leaf10, leaf11] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [root.id],
queueRunnerFactory: queueRunner
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(11);
queueableFns[0].fn();
expect(leaf1.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[2].fn();
expect(leaf3.execute).toHaveBeenCalled();
queueableFns[3].fn();
expect(leaf4.execute).toHaveBeenCalled();
queueableFns[4].fn();
expect(leaf5.execute).toHaveBeenCalled();
queueableFns[5].fn();
expect(leaf6.execute).toHaveBeenCalled();
queueableFns[6].fn();
expect(leaf7.execute).toHaveBeenCalled();
queueableFns[7].fn();
expect(leaf8.execute).toHaveBeenCalled();
queueableFns[8].fn();
expect(leaf9.execute).toHaveBeenCalled();
queueableFns[9].fn();
expect(leaf10.execute).toHaveBeenCalled();
queueableFns[10].fn();
expect(leaf11.execute).toHaveBeenCalled();
});
it("runs nodes in a custom order when orderChildren is overrided", function() {
var leaf1 = new Leaf(),
leaf2 = new Leaf(),
leaf3 = new Leaf(),
leaf4 = new Leaf(),
leaf5 = new Leaf(),
leaf6 = new Leaf(),
leaf7 = new Leaf(),
leaf8 = new Leaf(),
leaf9 = new Leaf(),
leaf10 = new Leaf(),
leaf11 = new Leaf(),
root = new Node({ children: [leaf1, leaf2, leaf3, leaf4, leaf5, leaf6, leaf7, leaf8, leaf9, leaf10, leaf11] }),
queueRunner = jasmine.createSpy('queueRunner'),
processor = new j$.TreeProcessor({
tree: root,
runnableIds: [root.id],
queueRunnerFactory: queueRunner,
orderChildren: function(node) {
var children = node.children.slice();
return children.reverse();
}
});
processor.execute();
var queueableFns = queueRunner.calls.mostRecent().args[0].queueableFns;
expect(queueableFns.length).toBe(11);
queueableFns[0].fn();
expect(leaf11.execute).toHaveBeenCalled();
queueableFns[1].fn();
expect(leaf10.execute).toHaveBeenCalled();
queueableFns[2].fn();
expect(leaf9.execute).toHaveBeenCalled();
queueableFns[3].fn();
expect(leaf8.execute).toHaveBeenCalled();
queueableFns[4].fn();
expect(leaf7.execute).toHaveBeenCalled();
queueableFns[5].fn();
expect(leaf6.execute).toHaveBeenCalled();
queueableFns[6].fn();
expect(leaf5.execute).toHaveBeenCalled();
queueableFns[7].fn();
expect(leaf4.execute).toHaveBeenCalled();
queueableFns[8].fn();
expect(leaf3.execute).toHaveBeenCalled();
queueableFns[9].fn();
expect(leaf2.execute).toHaveBeenCalled();
queueableFns[10].fn();
expect(leaf1.execute).toHaveBeenCalled();
});
});

View File

@@ -22,7 +22,7 @@ describe("Any", function() {
expect(any.asymmetricMatch({})).toBe(true);
});
it("matches a Boolean", function() {
var any = new j$.Any(Boolean);
@@ -39,8 +39,14 @@ describe("Any", function() {
it("jasmineToString's itself", function() {
var any = new j$.Any(Number);
expect(any.jasmineToString()).toMatch('<jasmine.any');
expect(any.jasmineToString()).toMatch('Number');
expect(any.jasmineToString()).toEqual('<jasmine.any(Number)>');
});
describe("when called without an argument", function() {
it("tells the user to pass a constructor or use jasmine.anything()", function() {
expect(function() {
new j$.Any();
}).toThrowError(TypeError, /constructor.*anything/);
});
});
});

View File

@@ -55,4 +55,35 @@ describe("ObjectContaining", function() {
expect(containing.asymmetricMatch({})).toBe(false);
});
it("matches defined properties", function(){
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
var containing = new j$.ObjectContaining({ foo: "fooVal" });
var definedPropertyObject = {};
Object.defineProperty(definedPropertyObject, "foo", {
get: function() { return "fooVal" }
});
expect(containing.asymmetricMatch(definedPropertyObject)).toBe(true);
});
it("matches prototype properties", function(){
var containing = new j$.ObjectContaining({ foo: "fooVal" });
var prototypeObject = {foo: "fooVal"};
var obj;
if (Object.create) {
obj = Object.create(prototypeObject);
} else {
function Foo() {}
Foo.prototype = prototypeObject;
Foo.prototype.constructor = Foo;
obj = new Foo();
}
expect(containing.asymmetricMatch(obj)).toBe(true);
});
});

View File

@@ -207,7 +207,6 @@ describe("Env integration", function() {
var env = new j$.Env();
env.addReporter({jasmineDone: done});
env.describe("tests", function() {
var firstTimeThrough = true, firstSpecContext, secondSpecContext;
@@ -612,8 +611,6 @@ describe("Env integration", function() {
expect(calls).toEqual([
"before",
"first spec",
"after",
"before",
"second spec",
"after"
]);
@@ -861,6 +858,36 @@ describe("Env integration", function() {
env.execute();
});
it("should not use the mock clock for asynchronous timeouts", function(){
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [ "specDone", "jasmineDone" ]),
clock = env.clock;
reporter.jasmineDone.and.callFake(function() {
expect(reporter.specDone.calls.count()).toEqual(1);
expect(reporter.specDone.calls.argsFor(0)[0]).toEqual(jasmine.objectContaining({status: 'passed'}));
});
env.addReporter(reporter);
j$.DEFAULT_TIMEOUT_INTERVAL = 5;
env.beforeAll(function() {
clock.install();
});
env.afterAll(function() {
clock.uninstall();
});
env.it("spec that should not time out", function(done) {
clock.tick(6);
expect(true).toEqual(true);
done();
});
env.execute();
});
it("should wait the specified interval before reporting an afterAll that fails to call done", function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReport', ['jasmineDone','suiteDone']);
@@ -971,9 +998,6 @@ describe("Env integration", function() {
env.addReporter({
specDone: specDone,
specStarted: function() {
jasmine.clock().tick(1);
},
jasmineDone: function() {
expect(specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'has a default message',
@@ -1033,6 +1057,10 @@ describe("Env integration", function() {
});
env.execute();
jasmine.clock().tick(1);
jasmine.clock().tick(1);
jasmine.clock().tick(1);
jasmine.clock().tick(1);
});
});
@@ -1086,6 +1114,78 @@ describe("Env integration", function() {
env.execute();
});
it('should run focused tests inside an xdescribe', function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
totalSpecsDefined: 1
});
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'with a fit spec',
status: 'failed'
}));
done();
});
env.addReporter(reporter);
env.xdescribe("xd suite", function() {
env.fit("with a fit spec", function() {
env.expect(true).toBe(false);
});
});
env.execute();
});
it('should run focused suites inside an xdescribe', function(done) {
var env = new j$.Env(),
reporter = jasmine.createSpyObj('fakeReporter', [
"jasmineStarted",
"jasmineDone",
"suiteStarted",
"suiteDone",
"specStarted",
"specDone"
]);
reporter.jasmineDone.and.callFake(function() {
expect(reporter.jasmineStarted).toHaveBeenCalledWith({
totalSpecsDefined: 1
});
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'with a spec',
status: 'failed'
}));
done();
});
env.addReporter(reporter);
env.xdescribe("xd suite", function() {
env.fdescribe("fd suite", function() {
env.it("with a spec", function() {
env.expect(true).toBe(false);
});
});
});
env.execute();
});
});
it("should report as expected", function(done) {
@@ -1105,6 +1205,27 @@ describe("Env integration", function() {
});
expect(reporter.specDone.calls.count()).toBe(5);
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'with a top level spec',
status: 'passed'
}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: "with an x'ed spec",
status: 'pending'
}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'with a spec',
status: 'failed'
}));
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({
description: 'is pending',
status: 'pending'
}));
var suiteResult = reporter.suiteStarted.calls.argsFor(0)[0];
expect(suiteResult.description).toEqual("A Suite");
@@ -1118,7 +1239,7 @@ describe("Env integration", function() {
env.expect(true).toBe(true);
});
env.describe("with a nested suite", function() {
env.xit("with a pending spec", function() {
env.xit("with an x'ed spec", function() {
env.expect(true).toBe(true);
});
env.it("with a spec", function() {
@@ -1126,9 +1247,9 @@ describe("Env integration", function() {
});
});
env.describe('with only pending specs', function() {
env.describe('with only non-executable specs', function() {
env.it('is pending');
env.xit('is pending', function() {
env.xit('is xed', function() {
env.expect(true).toBe(true);
});
});
@@ -1177,9 +1298,10 @@ describe("Env integration", function() {
totalSpecsDefined: 1
});
expect(reporter.specDone).not.toHaveBeenCalled();
expect(reporter.suiteDone.calls.count()).toBe(3);
expect(reporter.specDone).toHaveBeenCalledWith(jasmine.objectContaining({ status: 'pending' }));
expect(reporter.suiteDone).toHaveBeenCalledWith(jasmine.objectContaining({ description: 'xd out', status: 'pending' }));
expect(reporter.suiteDone.calls.count()).toBe(4);
done();
});
@@ -1188,8 +1310,10 @@ describe("Env integration", function() {
env.describe("A Suite", function() {
env.describe("nested", function() {
env.xdescribe("xd out", function() {
env.it("with a spec", function() {
env.expect(true).toBe(false);
env.describe("nested again", function() {
env.it("with a spec", function() {
env.expect(true).toBe(false);
});
});
});
});

View File

@@ -1,6 +1,5 @@
describe("jasmine spec running", function () {
var env;
var fakeTimer;
beforeEach(function() {
env = new j$.Env();
@@ -61,13 +60,17 @@ describe("jasmine spec running", function () {
expect(bar).toEqual(0);
expect(baz).toEqual(0);
expect(quux).toEqual(0);
nested.execute(function() {
var assertions = function() {
expect(foo).toEqual(1);
expect(bar).toEqual(1);
expect(baz).toEqual(1);
expect(quux).toEqual(1);
done();
});
};
env.addReporter({ jasmineDone: assertions });
env.execute();
});
it("should permit nested describes", function(done) {
@@ -214,10 +217,10 @@ describe("jasmine spec running", function () {
"beforeEach1",
"beforeEach2",
"outer it 1",
"afterEach2",
"afterEach1",
"runner afterEach2",
"runner afterEach1"
"afterEach2",
"runner afterEach1",
"runner afterEach2"
];
expect(actions).toEqual(expected);
done();
@@ -289,7 +292,7 @@ describe("jasmine spec running", function () {
env.execute();
});
it('should run beforeAlls and afterAlls as beforeEachs and afterEachs in the order declared when runnablesToRun is provided', function(done) {
it('should run beforeAlls and afterAlls in the order declared when runnablesToRun is provided', function(done) {
var actions = [],
spec,
spec2;
@@ -342,17 +345,13 @@ describe("jasmine spec running", function () {
"inner beforeAll",
"runner beforeEach",
"inner beforeEach",
"it",
"it2",
"inner afterEach",
"runner afterEach",
"inner afterAll",
"runner afterAll",
"runner beforeAll",
"inner beforeAll",
"runner beforeEach",
"inner beforeEach",
"it2",
"it",
"inner afterEach",
"runner afterEach",
"inner afterAll",
@@ -363,7 +362,7 @@ describe("jasmine spec running", function () {
};
env.addReporter({jasmineDone: assertions});
env.execute([spec.id, spec2.id]);
env.execute([spec2.id, spec.id]);
});
it('only runs *Alls once in a focused suite', function(done){
@@ -416,9 +415,7 @@ describe("jasmine spec running", function () {
'beforeEach',
'spec in fdescribe',
'afterEach',
'afterAll',
'beforeAll',
'beforeEach',
'focused spec',
'afterEach',
@@ -549,10 +546,14 @@ describe("jasmine spec running", function () {
pendingSpec = env.it("I am a pending spec");
});
suite.execute(function() {
var assertions = function() {
expect(pendingSpec.status()).toBe("pending");
done();
});
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
// TODO: is this useful? It doesn't catch syntax errors
@@ -603,4 +604,195 @@ describe("jasmine spec running", function () {
));
});
it("re-enters suites that have no *Alls", function(done) {
var actions = [],
spec1, spec2, spec3;
env.describe("top", function() {
spec1 = env.it("spec1", function() {
actions.push("spec1");
});
spec2 = env.it("spec2", function() {
actions.push("spec2");
});
});
spec3 = env.it("spec3", function() {
actions.push("spec3");
});
env.addReporter({
jasmineDone: function() {
expect(actions).toEqual(["spec2", "spec3", "spec1"]);
done();
}
});
env.execute([spec2.id, spec3.id, spec1.id]);
});
it("refuses to re-enter suites with a beforeAll", function() {
var actions = [],
spec1, spec2, spec3;
env.describe("top", function() {
env.beforeAll(function() {});
spec1 = env.it("spec1", function() {
actions.push("spec1");
});
spec2 = env.it("spec2", function() {
actions.push("spec2");
});
});
spec3 = env.it("spec3", function() {
actions.push("spec3");
});
env.addReporter({
jasmineDone: function() {
expect(actions).toEqual([]);
done();
}
});
expect(function() {
env.execute([spec2.id, spec3.id, spec1.id]);
}).toThrowError(/beforeAll/);
});
it("refuses to re-enter suites with a afterAll", function() {
var actions = [],
spec1, spec2, spec3;
env.describe("top", function() {
env.afterAll(function() {});
spec1 = env.it("spec1", function() {
actions.push("spec1");
});
spec2 = env.it("spec2", function() {
actions.push("spec2");
});
});
spec3 = env.it("spec3", function() {
actions.push("spec3");
});
env.addReporter({
jasmineDone: function() {
expect(actions).toEqual([]);
done();
}
});
expect(function() {
env.execute([spec2.id, spec3.id, spec1.id]);
}).toThrowError(/afterAll/);
});
it("should run the tests in a consistent order when a seed is supplied", function(done) {
var actions = [];
env.randomizeTests(true);
env.seed('123456');
env.beforeEach(function () {
actions.push('topSuite beforeEach');
});
env.afterEach(function () {
actions.push('topSuite afterEach');
});
env.describe('Something', function() {
env.beforeEach(function() {
actions.push('outer beforeEach');
});
env.afterEach(function() {
actions.push('outer afterEach');
});
env.it('does it 1', function() {
actions.push('outer it 1');
});
env.describe('Inner 1', function() {
env.beforeEach(function() {
actions.push('inner 1 beforeEach');
});
env.afterEach(function() {
actions.push('inner 1 afterEach');
});
env.it('does it 2', function() {
actions.push('inner 1 it');
});
});
env.it('does it 3', function() {
actions.push('outer it 2');
});
env.describe('Inner 2', function() {
env.beforeEach(function() {
actions.push('inner 2 beforeEach');
});
env.afterEach(function() {
actions.push('inner 2 afterEach');
});
env.it('does it 2', function() {
actions.push('inner 2 it');
});
});
});
var assertions = function() {
var expected = [
'topSuite beforeEach',
'outer beforeEach',
'outer it 2',
'outer afterEach',
'topSuite afterEach',
'topSuite beforeEach',
'outer beforeEach',
'inner 2 beforeEach',
'inner 2 it',
'inner 2 afterEach',
'outer afterEach',
'topSuite afterEach',
'topSuite beforeEach',
'outer beforeEach',
'inner 1 beforeEach',
'inner 1 it',
'inner 1 afterEach',
'outer afterEach',
'topSuite afterEach',
'topSuite beforeEach',
'outer beforeEach',
'outer it 1',
'outer afterEach',
'topSuite afterEach'
];
expect(actions).toEqual(expected);
done();
};
env.addReporter({jasmineDone: assertions});
env.execute();
});
});

View File

@@ -171,6 +171,33 @@ describe("matchersUtil", function() {
expect(j$.matchersUtil.equals(a,b)).toBe(true);
});
it("passes for equivalent objects from different vm contexts", function() {
if (typeof require !== 'function') {
return;
}
var vm = require('vm');
var sandbox = {
obj: null
};
vm.runInNewContext('obj = {a: 1, b: 2}', sandbox);
expect(j$.matchersUtil.equals(sandbox.obj, {a: 1, b: 2})).toBe(true);
});
it("passes for equivalent arrays from different vm contexts", function() {
if (typeof require !== 'function') {
return;
}
var vm = require('vm');
var sandbox = {
arr: null
};
vm.runInNewContext('arr = [1, 2]', sandbox);
expect(j$.matchersUtil.equals(sandbox.arr, [1, 2])).toBe(true);
});
it("passes when Any is used", function() {
var number = 3,
anyNumber = new j$.Any(Number);

View File

@@ -0,0 +1,81 @@
describe("toHaveBeenCalledTimes", function() {
it("passes when the actual matches the expected", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
calledSpy = j$.createSpy('called-spy'),
result;
calledSpy();
result = matcher.compare(calledSpy, 1);
expect(result.pass).toBe(true);
});
it("fails when expected numbers is not supplied", function(){
var matcher = j$.matchers.toHaveBeenCalledTimes(),
spy = j$.createSpy('spy'),
result;
spy();
expect(function() {
matcher.compare(spy);
}).toThrowError('Expected times failed is required as an argument.');
});
it("fails when the actual was called less than the expected", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
uncalledSpy = j$.createSpy('uncalled spy'),
result;
result = matcher.compare(uncalledSpy, 2);
expect(result.pass).toBe(false);
});
it("fails when the actual was called more than expected", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
uncalledSpy = j$.createSpy('uncalled spy'),
result;
uncalledSpy();
uncalledSpy();
result = matcher.compare(uncalledSpy, 1);
expect(result.pass).toBe(false);
});
it("throws an exception when the actual is not a spy", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
fn = function() {};
expect(function() {
matcher.compare(fn);
}).toThrowError("Expected a spy, but got Function.");
});
it("has a custom message on failure that tells it was called only once", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
spy = j$.createSpy('sample-spy'),
result;
spy();
spy();
spy();
spy();
result = matcher.compare(spy, 1);
expect(result.message).toEqual('Expected spy sample-spy to have been called once. It was called ' + 4 + ' times.');
});
it("has a custom message on failure that tells how many times it was called", function() {
var matcher = j$.matchers.toHaveBeenCalledTimes(),
spy = j$.createSpy('sample-spy'),
result;
spy();
spy();
spy();
spy();
result = matcher.compare(spy, 2);
expect(result.message).toEqual('Expected spy sample-spy to have been called 2 times. It was called ' + 4 + ' times.');
});
});

View File

@@ -146,7 +146,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error();
},
@@ -162,7 +162,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
CustomError = function CustomError(arg) { arg.x },
fn = function() {
throw new CustomError({ x: 1 });
@@ -170,7 +170,6 @@ describe("toThrowError", function() {
result;
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
result = matcher.compare(fn, CustomError);
@@ -182,7 +181,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new Error();
},
@@ -198,7 +197,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new TypeError("foo");
},
@@ -214,7 +213,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
CustomError = function CustomError(arg) { this.message = arg.message },
fn = function() {
throw new CustomError({message: "foo"});
@@ -222,7 +221,6 @@ describe("toThrowError", function() {
result;
CustomError.prototype = new Error();
CustomError.prototype.constructor = CustomError;
result = matcher.compare(fn, CustomError, "foo");
@@ -234,7 +232,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new TypeError("foo");
},
@@ -250,7 +248,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(true)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new TypeError("foo");
},
@@ -266,7 +264,7 @@ describe("toThrowError", function() {
var util = {
equals: jasmine.createSpy('delegated-equal').and.returnValue(false)
},
matcher = j$.matchers.toThrowError(util),
matcher = j$.matchers.toThrowError(),
fn = function() {
throw new TypeError("foo");
},

View File

@@ -14,20 +14,20 @@ describe("New HtmlReporter", function() {
// Main top-level elements
expect(container.querySelector("div.jasmine_html-reporter")).toBeTruthy();
expect(container.querySelector("div.banner")).toBeTruthy();
expect(container.querySelector("div.alert")).toBeTruthy();
expect(container.querySelector("div.results")).toBeTruthy();
expect(container.querySelector("div.jasmine-banner")).toBeTruthy();
expect(container.querySelector("div.jasmine-alert")).toBeTruthy();
expect(container.querySelector("div.jasmine-results")).toBeTruthy();
expect(container.querySelector("ul.symbol-summary")).toBeTruthy();
expect(container.querySelector("ul.jasmine-symbol-summary")).toBeTruthy();
// title banner
var banner = container.querySelector(".banner");
var banner = container.querySelector(".jasmine-banner");
var title = banner.querySelector("a.title");
var title = banner.querySelector("a.jasmine-title");
expect(title.getAttribute('href')).toEqual('http://jasmine.github.io/');
expect(title.getAttribute('target')).toEqual('_blank');
var version = banner.querySelector(".version"),
var version = banner.querySelector(".jasmine-version"),
versionText = 'textContent' in version ? version.textContent : version.innerText;
expect(versionText).toEqual(j$.version);
});
@@ -90,8 +90,8 @@ describe("New HtmlReporter", function() {
failedExpectations: []
});
expect(console.error).toHaveBeenCalledWith("Spec \'Some Name\' has no expectations.");
var specEl = container.querySelector('.symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("empty");
var specEl = container.querySelector('.jasmine-symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("jasmine-empty");
});
it("reports the status symbol of a disabled spec", function() {
@@ -108,8 +108,8 @@ describe("New HtmlReporter", function() {
reporter.specDone({id: 789, status: "disabled", fullName: "symbols should have titles", passedExpectations: [], failedExpectations: []});
var specEl = container.querySelector('.symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("disabled");
var specEl = container.querySelector('.jasmine-symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("jasmine-disabled");
expect(specEl.getAttribute("id")).toEqual("spec_789");
expect(specEl.getAttribute("title")).toEqual("symbols should have titles");
});
@@ -128,8 +128,8 @@ describe("New HtmlReporter", function() {
reporter.specDone({id: 789, status: "pending", passedExpectations: [], failedExpectations: []});
var specEl = container.querySelector('.symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("pending");
var specEl = container.querySelector('.jasmine-symbol-summary li');
expect(specEl.getAttribute("class")).toEqual("jasmine-pending");
expect(specEl.getAttribute("id")).toEqual("spec_789");
});
@@ -147,9 +147,9 @@ describe("New HtmlReporter", function() {
reporter.specDone({id: 123, status: "passed", passedExpectations: [{passed: true}], failedExpectations: []});
var statuses = container.querySelector(".symbol-summary");
var statuses = container.querySelector(".jasmine-symbol-summary");
var specEl = statuses.querySelector("li");
expect(specEl.getAttribute("class")).toEqual("passed");
expect(specEl.getAttribute("class")).toEqual("jasmine-passed");
expect(specEl.getAttribute("id")).toEqual("spec_123");
});
@@ -173,8 +173,8 @@ describe("New HtmlReporter", function() {
passedExpectations: []
});
var specEl = container.querySelector(".symbol-summary li");
expect(specEl.getAttribute("class")).toEqual("failed");
var specEl = container.querySelector(".jasmine-symbol-summary li");
expect(specEl.getAttribute("class")).toEqual("jasmine-failed");
expect(specEl.getAttribute("id")).toEqual("spec_345");
});
});
@@ -198,11 +198,11 @@ describe("New HtmlReporter", function() {
reporter.suiteDone({ status: 'failed', failedExpectations: [{ message: 'My Other Exception' }] });
reporter.jasmineDone({});
var alertBars = container.querySelectorAll(".alert .bar");
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(3);
expect(alertBars[1].innerHTML).toMatch(/My After All Exception/);
expect(alertBars[1].getAttribute("class")).toEqual('bar errored');
expect(alertBars[1].getAttribute("class")).toEqual('jasmine-bar jasmine-errored');
expect(alertBars[2].innerHTML).toMatch(/My Other Exception/);
});
});
@@ -238,7 +238,7 @@ describe("New HtmlReporter", function() {
reporter.suiteDone({id: 1});
reporter.jasmineDone({});
var summary = container.querySelector('.summary');
var summary = container.querySelector('.jasmine-summary');
var suite = summary.childNodes[0];
var specs = suite.childNodes[1];
var spec = specs.childNodes[0];
@@ -266,7 +266,7 @@ describe("New HtmlReporter", function() {
timer.elapsed.and.returnValue(100);
reporter.jasmineDone();
var duration = container.querySelector(".banner .duration");
var duration = container.querySelector(".jasmine-alert .jasmine-duration");
expect(duration.innerHTML).toMatch(/finished in 0.1s/);
});
@@ -334,7 +334,7 @@ describe("New HtmlReporter", function() {
reporter.suiteDone({id: 1});
reporter.jasmineDone({});
var summary = container.querySelector(".summary");
var summary = container.querySelector(".jasmine-summary");
expect(summary.childNodes.length).toEqual(1);
@@ -346,7 +346,7 @@ describe("New HtmlReporter", function() {
var node = outerSuite.childNodes[i];
classes.push(node.getAttribute("class"));
}
expect(classes).toEqual(["suite-detail", "specs", "suite", "specs"]);
expect(classes).toEqual(["jasmine-suite-detail", "jasmine-specs", "jasmine-suite", "jasmine-specs"]);
var suiteDetail = outerSuite.childNodes[0];
var suiteLink = suiteDetail.childNodes[0];
@@ -355,7 +355,7 @@ describe("New HtmlReporter", function() {
var specs = outerSuite.childNodes[1];
var spec = specs.childNodes[0];
expect(spec.getAttribute("class")).toEqual("passed");
expect(spec.getAttribute("class")).toEqual("jasmine-passed");
expect(spec.getAttribute("id")).toEqual("spec-123");
var specLink = spec.childNodes[0];
@@ -364,6 +364,40 @@ describe("New HtmlReporter", function() {
// expect(specLink.getAttribute("title")).toEqual("A Suite with a spec");
});
it("has an options menu", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var trigger = container.querySelector('.jasmine-run-options .jasmine-trigger'),
payload = container.querySelector('.jasmine-run-options .jasmine-payload');
expect(payload.className).not.toContain('jasmine-open');
trigger.onclick();
expect(payload.className).toContain('jasmine-open');
trigger.onclick();
expect(payload.className).not.toContain('jasmine-open');
});
describe("UI for raising/catching exceptions", function() {
it("should be unchecked if the env is catching", function() {
var env = new j$.Env(),
@@ -385,7 +419,7 @@ describe("New HtmlReporter", function() {
reporter.initialize();
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".raise");
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
expect(raisingExceptionsUI.checked).toBe(false);
});
@@ -410,7 +444,7 @@ describe("New HtmlReporter", function() {
env.catchExceptions(false);
reporter.jasmineDone({});
var raisingExceptionsUI = container.querySelector(".raise");
var raisingExceptionsUI = container.querySelector(".jasmine-raise");
expect(raisingExceptionsUI.checked).toBe(true);
});
@@ -436,12 +470,228 @@ describe("New HtmlReporter", function() {
reporter.initialize();
reporter.jasmineDone({});
var input = container.querySelector(".raise");
var input = container.querySelector(".jasmine-raise");
input.click();
expect(exceptionsClickHandler).toHaveBeenCalled();
});
});
describe("UI for throwing errors on expectation failures", function() {
it("should be unchecked if not throwing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
expect(throwingExpectationsUI.checked).toBe(false);
});
it("should be checked if throwing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.throwOnExpectationFailure(true);
reporter.initialize();
reporter.jasmineDone({});
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
expect(throwingExpectationsUI.checked).toBe(true);
});
it("should affect the query param for throw expectation failures", function() {
var env = new j$.Env(),
container = document.createElement("div"),
throwingExceptionHandler = jasmine.createSpy('throwingExceptions'),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
onThrowExpectationsClick: throwingExceptionHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var throwingExpectationsUI = container.querySelector(".jasmine-throw");
throwingExpectationsUI.click();
expect(throwingExceptionHandler).toHaveBeenCalled();
});
});
describe("UI for running tests in random order", function() {
it("should be unchecked if not randomizing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var randomUI = container.querySelector(".jasmine-random");
expect(randomUI.checked).toBe(false);
});
it("should be checked if randomizing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
env.randomizeTests(true);
reporter.initialize();
reporter.jasmineDone({});
var randomUI = container.querySelector(".jasmine-random");
expect(randomUI.checked).toBe(true);
});
it("should affect the query param for random tests", function() {
var env = new j$.Env(),
container = document.createElement("div"),
randomHandler = jasmine.createSpy('randomHandler'),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
onRandomClick: randomHandler,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({});
var randomUI = container.querySelector(".jasmine-random");
randomUI.click();
expect(randomHandler).toHaveBeenCalled();
});
it("should show the seed bar if randomizing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone({
order: {
random: true,
seed: '424242'
}
});
var seedBar = container.querySelector(".jasmine-seed-bar");
var seedBarText = 'textContent' in seedBar ? seedBar.textContent : seedBar.innerText;
expect(seedBarText).toBe(', randomized with seed 424242');
var seedLink = container.querySelector(".jasmine-seed-bar a");
expect(seedLink.getAttribute('href')).toBe('?seed=424242');
});
it("should not show the current seed bar if not randomizing", function() {
var env = new j$.Env(),
container = document.createElement("div"),
getContainer = function() {
return container;
},
reporter = new j$.HtmlReporter({
env: env,
getContainer: getContainer,
createElement: function() {
return document.createElement.apply(document, arguments);
},
createTextNode: function() {
return document.createTextNode.apply(document, arguments);
}
});
reporter.initialize();
reporter.jasmineDone();
var seedBar = container.querySelector(".jasmine-seed-bar");
expect(seedBar).toBeNull();
});
});
it("shows a message if no specs are run", function(){
var env, container, reporter;
env = new j$.Env();
@@ -458,8 +708,8 @@ describe("New HtmlReporter", function() {
reporter.jasmineStarted({});
reporter.jasmineDone({});
var alertBars = container.querySelectorAll(".alert .bar");
expect(alertBars[0].getAttribute('class')).toMatch(/skipped/);
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-skipped/);
expect(alertBars[0].innerHTML).toMatch(/No specs found/);
});
@@ -498,21 +748,21 @@ describe("New HtmlReporter", function() {
});
it("reports the specs counts", function() {
var alertBars = container.querySelectorAll(".alert .bar");
var alertBars = container.querySelectorAll(".jasmine-alert .jasmine-bar");
expect(alertBars.length).toEqual(1);
expect(alertBars[0].getAttribute('class')).toMatch(/passed/);
expect(alertBars[0].getAttribute('class')).toMatch(/jasmine-passed/);
expect(alertBars[0].innerHTML).toMatch(/2 specs, 0 failures/);
});
it("reports no failure details", function() {
var specFailure = container.querySelector(".failures");
var specFailure = container.querySelector(".jasmine-failures");
expect(specFailure.childNodes.length).toEqual(0);
});
it("reports no pending specs", function() {
var alertBar = container.querySelector(".alert .bar");
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
expect(alertBar.innerHTML).not.toMatch(/pending spec[s]/);
});
@@ -548,19 +798,19 @@ describe("New HtmlReporter", function() {
});
it("reports the pending specs count", function() {
var alertBar = container.querySelector(".alert .bar");
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
expect(alertBar.innerHTML).toMatch(/1 spec, 0 failures, 1 pending spec/);
});
it("reports no failure details", function() {
var specFailure = container.querySelector(".failures");
var specFailure = container.querySelector(".jasmine-failures");
expect(specFailure.childNodes.length).toEqual(0);
});
it("displays the custom pending reason", function() {
var pendingDetails = container.querySelector(".summary .pending");
var pendingDetails = container.querySelector(".jasmine-summary .jasmine-pending");
expect(pendingDetails.innerHTML).toContain("my custom pending reason");
});
@@ -607,37 +857,37 @@ describe("New HtmlReporter", function() {
});
it("reports the specs counts", function() {
var alertBar = container.querySelector(".alert .bar");
var alertBar = container.querySelector(".jasmine-alert .jasmine-bar");
expect(alertBar.getAttribute('class')).toMatch(/failed/);
expect(alertBar.getAttribute('class')).toMatch(/jasmine-failed/);
expect(alertBar.innerHTML).toMatch(/2 specs, 1 failure/);
});
it("reports failure messages and stack traces", function() {
var specFailures = container.querySelector(".failures");
var specFailures = container.querySelector(".jasmine-failures");
var failure = specFailures.childNodes[0];
expect(failure.getAttribute("class")).toMatch(/failed/);
expect(failure.getAttribute("class")).toMatch(/spec-detail/);
expect(failure.getAttribute("class")).toMatch(/jasmine-failed/);
expect(failure.getAttribute("class")).toMatch(/jasmine-spec-detail/);
var specDiv = failure.childNodes[0];
expect(specDiv.getAttribute("class")).toEqual("description");
expect(specDiv.getAttribute("class")).toEqual("jasmine-description");
var specLink = specDiv.childNodes[0];
expect(specLink.getAttribute("title")).toEqual("a suite with a failing spec");
expect(specLink.getAttribute("href")).toEqual("?foo=bar&spec=a suite with a failing spec");
var message = failure.childNodes[1].childNodes[0];
expect(message.getAttribute("class")).toEqual("result-message");
expect(message.getAttribute("class")).toEqual("jasmine-result-message");
expect(message.innerHTML).toEqual("a failure message");
var stackTrace = failure.childNodes[1].childNodes[1];
expect(stackTrace.getAttribute("class")).toEqual("stack-trace");
expect(stackTrace.getAttribute("class")).toEqual("jasmine-stack-trace");
expect(stackTrace.innerHTML).toEqual("a stack trace");
});
it("allows switching between failure details and the spec summary", function() {
var menuBar = container.querySelectorAll(".bar")[1];
var menuBar = container.querySelectorAll(".jasmine-bar")[1];
expect(menuBar.getAttribute("class")).not.toMatch(/hidden/);
@@ -648,7 +898,7 @@ describe("New HtmlReporter", function() {
it("sets the reporter to 'Failures List' mode", function() {
var reporterNode = container.querySelector(".jasmine_html-reporter");
expect(reporterNode.getAttribute("class")).toMatch("failure-list");
expect(reporterNode.getAttribute("class")).toMatch("jasmine-failure-list");
});
});
});

View File

@@ -1,5 +1,6 @@
describe('npm package', function() {
var path = require('path'),
temp = require('temp').track(),
fs = require('fs');
beforeAll(function() {
@@ -7,9 +8,7 @@ describe('npm package', function() {
pack = shell.exec('npm pack', { silent: true });
this.tarball = pack.output.split('\n')[0];
this.tmpDir = '/tmp/jasmine-core';
fs.mkdirSync(this.tmpDir);
this.tmpDir = temp.mkdirSync(); // automatically deleted on exit
var untar = shell.exec('tar -xzf ' + this.tarball + ' -C ' + this.tmpDir, { silent: true });
expect(untar.code).toBe(0);
@@ -44,8 +43,6 @@ describe('npm package', function() {
};
fs.unlink(this.tarball);
fs.readdirSync(this.tmpDir).forEach(cleanup.bind(null, this.tmpDir));
fs.rmdirSync(this.tmpDir);
});
it('has a root path', function() {

View File

@@ -5,5 +5,6 @@
],
"helper_files": [
"helpers/nodeDefineJasmineUnderTest.js"
]
],
"random": true
}

View File

@@ -7,3 +7,4 @@ helpers:
spec_files:
- 'performance/performance_test.js'
spec_dir: spec
random: true

View File

@@ -7,5 +7,6 @@
],
"helpers": [
"helpers/nodeDefineJasmineUnderTest.js"
]
],
"random": true
}

View File

@@ -22,5 +22,5 @@ spec_files:
- '**/*[Ss]pec.js'
- '!npmPackage/**/*'
spec_dir: spec
random: true

View File

@@ -1,5 +1,5 @@
getJasmineRequireObj().Clock = function() {
function Clock(global, delayedFunctionScheduler, mockDate) {
function Clock(global, delayedFunctionSchedulerFactory, mockDate) {
var self = this,
realTimingFunctions = {
setTimeout: global.setTimeout,
@@ -14,19 +14,24 @@ getJasmineRequireObj().Clock = function() {
clearInterval: clearInterval
},
installed = false,
delayedFunctionScheduler,
timer;
self.install = function() {
if(!originalTimingFunctionsIntact()) {
throw new Error('Jasmine Clock was unable to install over custom global timer functions. Is the clock already installed?');
}
replace(global, fakeTimingFunctions);
timer = fakeTimingFunctions;
delayedFunctionScheduler = delayedFunctionSchedulerFactory();
installed = true;
return self;
};
self.uninstall = function() {
delayedFunctionScheduler.reset();
delayedFunctionScheduler = null;
mockDate.uninstall();
replace(global, realTimingFunctions);
@@ -34,6 +39,15 @@ getJasmineRequireObj().Clock = function() {
installed = false;
};
self.withMock = function(closure) {
this.install();
try {
closure();
} finally {
this.uninstall();
}
};
self.mockDate = function(initialDate) {
mockDate.install(initialDate);
};
@@ -77,6 +91,13 @@ getJasmineRequireObj().Clock = function() {
return self;
function originalTimingFunctionsIntact() {
return global.setTimeout === realTimingFunctions.setTimeout &&
global.clearTimeout === realTimingFunctions.clearTimeout &&
global.setInterval === realTimingFunctions.setInterval &&
global.clearInterval === realTimingFunctions.clearInterval;
}
function legacyIE() {
//if these methods are polyfilled, apply will be present
return !(realTimingFunctions.setTimeout || realTimingFunctions.setInterval).apply;

View File

@@ -72,13 +72,6 @@ getJasmineRequireObj().DelayedFunctionScheduler = function() {
}
};
self.reset = function() {
currentTime = 0;
scheduledLookup = [];
scheduledFunctions = {};
delayedFnCount = 0;
};
return self;
function indexOfFirstToPass(array, testFn) {

View File

@@ -11,7 +11,7 @@ getJasmineRequireObj().Env = function(j$) {
var realSetTimeout = j$.getGlobal().setTimeout;
var realClearTimeout = j$.getGlobal().clearTimeout;
this.clock = new j$.Clock(global, new j$.DelayedFunctionScheduler(), new j$.MockDate(global));
this.clock = new j$.Clock(global, function () { return new j$.DelayedFunctionScheduler(); }, new j$.MockDate(global));
var runnableLookupTable = {};
var runnableResources = {};
@@ -19,6 +19,9 @@ getJasmineRequireObj().Env = function(j$) {
var currentSpec = null;
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var throwOnExpectationFailure = false;
var random = false;
var seed = null;
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
@@ -100,27 +103,21 @@ getJasmineRequireObj().Env = function(j$) {
delete runnableResources[id];
};
var beforeAndAfterFns = function(suite, runnablesExplictlySet) {
var beforeAndAfterFns = function(suite) {
return function() {
var befores = [],
afters = [],
beforeAlls = [],
afterAlls = [];
afters = [];
while(suite) {
befores = befores.concat(suite.beforeFns);
afters = afters.concat(suite.afterFns);
if (runnablesExplictlySet()) {
beforeAlls = beforeAlls.concat(suite.beforeAllFns);
afterAlls = afterAlls.concat(suite.afterAllFns);
}
afters = afters.concat(suite.afterFns.reverse());
suite = suite.parentSuite;
}
return {
befores: beforeAlls.reverse().concat(befores.reverse()),
afters: afters.concat(afterAlls)
befores: befores.reverse(),
afters: afters
};
};
};
@@ -166,10 +163,33 @@ getJasmineRequireObj().Env = function(j$) {
return j$.Spec.isPendingSpecException(e) || catchExceptions;
};
this.throwOnExpectationFailure = function(value) {
throwOnExpectationFailure = !!value;
};
this.throwingExpectationFailures = function() {
return throwOnExpectationFailure;
};
this.randomizeTests = function(value) {
random = !!value;
};
this.randomTests = function() {
return random;
};
this.seed = function(value) {
if (value) {
seed = value;
}
return seed;
};
var queueRunnerFactory = function(options) {
options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
options.timer = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
options.timeout = {setTimeout: realSetTimeout, clearTimeout: realClearTimeout};
options.fail = self.fail;
new j$.QueueRunner(options).execute();
@@ -190,26 +210,53 @@ getJasmineRequireObj().Env = function(j$) {
};
this.execute = function(runnablesToRun) {
if(runnablesToRun) {
runnablesExplictlySet = true;
} else if (focusedRunnables.length) {
runnablesExplictlySet = true;
runnablesToRun = focusedRunnables;
} else {
runnablesToRun = [topSuite.id];
if(!runnablesToRun) {
if (focusedRunnables.length) {
runnablesToRun = focusedRunnables;
} else {
runnablesToRun = [topSuite.id];
}
}
var allFns = [];
for(var i = 0; i < runnablesToRun.length; i++) {
var runnable = runnableLookupTable[runnablesToRun[i]];
allFns.push((function(runnable) { return { fn: function(done) { runnable.execute(done); } }; })(runnable));
var order = new j$.Order({
random: random,
seed: seed
});
var processor = new j$.TreeProcessor({
tree: topSuite,
runnableIds: runnablesToRun,
queueRunnerFactory: queueRunnerFactory,
nodeStart: function(suite) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
},
nodeComplete: function(suite, result) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
}
currentlyExecutingSuites.pop();
reporter.suiteDone(result);
},
orderChildren: function(node) {
return order.sort(node.children);
}
});
if(!processor.processTree().valid) {
throw new Error('Invalid order: would cause a beforeAll or afterAll to be run multiple times');
}
reporter.jasmineStarted({
totalSpecsDefined: totalSpecsDefined
});
queueRunnerFactory({queueableFns: allFns, onComplete: reporter.jasmineDone});
processor.execute(function() {
reporter.jasmineDone({
order: order
});
});
};
this.addReporter = function(reporterToAdd) {
@@ -233,39 +280,31 @@ getJasmineRequireObj().Env = function(j$) {
id: getNextSuiteId(),
description: description,
parentSuite: currentDeclarationSuite,
queueRunner: queueRunnerFactory,
onStart: suiteStarted,
expectationFactory: expectationFactory,
expectationResultFactory: expectationResultFactory,
runnablesExplictlySetGetter: runnablesExplictlySetGetter,
resultCallback: function(attrs) {
if (!suite.disabled) {
clearResourcesForRunnable(suite.id);
}
currentlyExecutingSuites.pop();
reporter.suiteDone(attrs);
}
throwOnExpectationFailure: throwOnExpectationFailure
});
runnableLookupTable[suite.id] = suite;
return suite;
function suiteStarted(suite) {
currentlyExecutingSuites.push(suite);
defaultResourcesForRunnable(suite.id, suite.parentSuite.id);
reporter.suiteStarted(suite.result);
}
};
this.describe = function(description, specDefinitions) {
var suite = suiteFactory(description);
if (specDefinitions.length > 0) {
throw new Error('describe does not expect a done parameter');
}
if (currentDeclarationSuite.markedPending) {
suite.pend();
}
addSpecsToSuite(suite, specDefinitions);
return suite;
};
this.xdescribe = function(description, specDefinitions) {
var suite = this.describe(description, specDefinitions);
suite.disable();
var suite = suiteFactory(description);
suite.pend();
addSpecsToSuite(suite, specDefinitions);
return suite;
};
@@ -326,17 +365,11 @@ getJasmineRequireObj().Env = function(j$) {
}
}
var runnablesExplictlySet = false;
var runnablesExplictlySetGetter = function(){
return runnablesExplictlySet;
};
var specFactory = function(description, fn, suite, timeout) {
totalSpecsDefined++;
var spec = new j$.Spec({
id: getNextSpecId(),
beforeAndAfterFns: beforeAndAfterFns(suite, runnablesExplictlySetGetter),
beforeAndAfterFns: beforeAndAfterFns(suite),
expectationFactory: expectationFactory,
resultCallback: specResultCallback,
getSpecName: function(spec) {
@@ -350,7 +383,8 @@ getJasmineRequireObj().Env = function(j$) {
queueableFn: {
fn: fn,
timeout: function() { return timeout || j$.DEFAULT_TIMEOUT_INTERVAL; }
}
},
throwOnExpectationFailure: throwOnExpectationFailure
});
runnableLookupTable[spec.id] = spec;
@@ -376,19 +410,22 @@ getJasmineRequireObj().Env = function(j$) {
this.it = function(description, fn, timeout) {
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
if (currentDeclarationSuite.markedPending) {
spec.pend();
}
currentDeclarationSuite.addChild(spec);
return spec;
};
this.xit = function() {
var spec = this.it.apply(this, arguments);
spec.pend();
spec.pend('Temporarily disabled with xit');
return spec;
};
this.fit = function(){
var spec = this.it.apply(this, arguments);
this.fit = function(description, fn, timeout){
var spec = specFactory(description, fn, currentDeclarationSuite, timeout);
currentDeclarationSuite.addChild(spec);
focusedRunnables.push(spec.id);
unfocusAncestor();
return spec;

View File

@@ -11,6 +11,7 @@ getJasmineRequireObj().JsApiReporter = function() {
this.started = false;
this.finished = false;
this.runDetails = {};
this.jasmineStarted = function() {
this.started = true;
@@ -20,8 +21,9 @@ getJasmineRequireObj().JsApiReporter = function() {
var executionTime;
this.jasmineDone = function() {
this.jasmineDone = function(runDetails) {
this.finished = true;
this.runDetails = runDetails;
executionTime = timer.elapsed();
status = 'done';
};

46
src/core/Order.js Normal file
View File

@@ -0,0 +1,46 @@
/*jshint bitwise: false*/
getJasmineRequireObj().Order = function() {
function Order(options) {
this.random = 'random' in options ? options.random : true;
var seed = this.seed = options.seed || generateSeed();
this.sort = this.random ? randomOrder : naturalOrder;
function naturalOrder(items) {
return items;
}
function randomOrder(items) {
var copy = items.slice();
copy.sort(function(a, b) {
return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id);
});
return copy;
}
function generateSeed() {
return String(Math.random()).slice(-5);
}
// Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function
// used to get a different output when the key changes slighly.
// We use your return to sort the children randomly in a consistent way when
// used in conjunction with a seed
function jenkinsHash(key) {
var hash, i;
for(hash = i = 0; i < key.length; ++i) {
hash += key.charCodeAt(i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
}
return Order;
};

View File

@@ -30,6 +30,8 @@ getJasmineRequireObj().pp = function(j$) {
this.emitScalar('HTMLNode');
} else if (value instanceof Date) {
this.emitScalar('Date(' + value + ')');
} else if (value.toString && typeof value === 'object' && !(value instanceof Array) && value.toString !== Object.prototype.toString) {
this.emitScalar(value.toString());
} else if (j$.util.arrayContains(this.seen, value)) {
this.emitScalar('<circular reference: ' + (j$.isArray_(value) ? 'Array' : 'Object') + '>');
} else if (j$.isArray_(value) || j$.isA_('Object', value)) {
@@ -93,6 +95,23 @@ getJasmineRequireObj().pp = function(j$) {
if(array.length > length){
this.append(', ...');
}
var self = this;
var first = array.length === 0;
this.iterateObject(array, function(property, isGetter) {
if (property.match(/^\d+$/)) {
return;
}
if (first) {
first = false;
} else {
self.append(', ');
}
self.formatProperty(array, property, isGetter);
});
this.append(' ]');
};
@@ -115,18 +134,22 @@ getJasmineRequireObj().pp = function(j$) {
self.append(', ');
}
self.append(property);
self.append(': ');
if (isGetter) {
self.append('<getter>');
} else {
self.format(obj[property]);
}
self.formatProperty(obj, property, isGetter);
});
this.append(' })');
};
StringPrettyPrinter.prototype.formatProperty = function(obj, property, isGetter) {
this.append(property);
this.append(': ');
if (isGetter) {
this.append('<getter>');
} else {
this.format(obj[property]);
}
};
StringPrettyPrinter.prototype.append = function(value) {
this.string += value;
};

View File

@@ -17,7 +17,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
this.onException = attrs.onException || function() {};
this.catchException = attrs.catchException || function() { return true; };
this.userContext = attrs.userContext || {};
this.timer = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
this.timeout = attrs.timeout || {setTimeout: setTimeout, clearTimeout: clearTimeout};
this.fail = attrs.fail || function() {};
}
@@ -57,7 +57,7 @@ getJasmineRequireObj().QueueRunner = function(j$) {
function attemptAsync(queueableFn) {
var clearTimeout = function () {
Function.prototype.apply.apply(self.timer.clearTimeout, [j$.getGlobal(), [timeoutId]]);
Function.prototype.apply.apply(self.timeout.clearTimeout, [j$.getGlobal(), [timeoutId]]);
},
next = once(function () {
clearTimeout(timeoutId);
@@ -71,9 +71,9 @@ getJasmineRequireObj().QueueRunner = function(j$) {
};
if (queueableFn.timeout) {
timeoutId = Function.prototype.apply.apply(self.timer.setTimeout, [j$.getGlobal(), [function() {
timeoutId = Function.prototype.apply.apply(self.timeout.setTimeout, [j$.getGlobal(), [function() {
var error = new Error('Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.');
onException(error, queueableFn);
onException(error);
next();
}, queueableFn.timeout()]]);
}
@@ -86,12 +86,12 @@ getJasmineRequireObj().QueueRunner = function(j$) {
}
}
function onException(e, queueableFn) {
function onException(e) {
self.onException(e);
}
function handleException(e, queueableFn) {
onException(e, queueableFn);
onException(e);
if (!self.catchException(e)) {
//TODO: set a var when we catch an exception and
//use a finally block to close the loop in a nice way..

View File

@@ -12,6 +12,7 @@ getJasmineRequireObj().Spec = function(j$) {
this.expectationResultFactory = attrs.expectationResultFactory || function() { };
this.queueRunnerFactory = attrs.queueRunnerFactory || function() {};
this.catchingExceptions = attrs.catchingExceptions || function() { return true; };
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
if (!this.queueableFn.fn) {
this.pend();
@@ -27,12 +28,16 @@ getJasmineRequireObj().Spec = function(j$) {
};
}
Spec.prototype.addExpectationResult = function(passed, data) {
Spec.prototype.addExpectationResult = function(passed, data, isError) {
var expectationResult = this.expectationResultFactory(data);
if (passed) {
this.result.passedExpectations.push(expectationResult);
} else {
this.result.failedExpectations.push(expectationResult);
if (this.throwOnExpectationFailure && !isError) {
throw new j$.errors.ExpectationFailed();
}
}
};
@@ -40,13 +45,13 @@ getJasmineRequireObj().Spec = function(j$) {
return this.expectationFactory(actual, this);
};
Spec.prototype.execute = function(onComplete) {
Spec.prototype.execute = function(onComplete, enabled) {
var self = this;
this.onStart(this);
if (this.markedPending || this.disabled) {
complete();
if (!this.isExecutable() || this.markedPending || enabled === false) {
complete(enabled);
return;
}
@@ -60,8 +65,8 @@ getJasmineRequireObj().Spec = function(j$) {
userContext: this.userContext()
});
function complete() {
self.result.status = self.status();
function complete(enabledAgain) {
self.result.status = self.status(enabledAgain);
self.resultCallback(self.result);
if (onComplete) {
@@ -76,13 +81,17 @@ getJasmineRequireObj().Spec = function(j$) {
return;
}
if (e instanceof j$.errors.ExpectationFailed) {
return;
}
this.addExpectationResult(false, {
matcherName: '',
passed: false,
expected: '',
actual: '',
error: e
});
}, true);
};
Spec.prototype.disable = function() {
@@ -96,8 +105,13 @@ getJasmineRequireObj().Spec = function(j$) {
}
};
Spec.prototype.status = function() {
if (this.disabled) {
Spec.prototype.getResult = function() {
this.result.status = this.status();
return this.result;
};
Spec.prototype.status = function(enabled) {
if (this.disabled || enabled === false) {
return 'disabled';
}
@@ -113,7 +127,7 @@ getJasmineRequireObj().Spec = function(j$) {
};
Spec.prototype.isExecutable = function() {
return !this.disabled && !this.markedPending;
return !this.disabled;
};
Spec.prototype.getFullName = function() {

View File

@@ -22,6 +22,17 @@ getJasmineRequireObj().SpyRegistry = function(j$) {
throw new Error(methodName + ' has already been spied upon');
}
var descriptor;
try {
descriptor = Object.getOwnPropertyDescriptor(obj, methodName);
} catch(e) {
// IE 8 doesn't support `definePropery` on non-DOM nodes
}
if (descriptor && !(descriptor.writable || descriptor.set)) {
throw new Error(methodName + ' is not declared writable or has no setter');
}
var spy = j$.createSpy(methodName, obj[methodName]);
currentSpies().push({

View File

@@ -1,21 +1,17 @@
getJasmineRequireObj().Suite = function() {
getJasmineRequireObj().Suite = function(j$) {
function Suite(attrs) {
this.env = attrs.env;
this.id = attrs.id;
this.parentSuite = attrs.parentSuite;
this.description = attrs.description;
this.onStart = attrs.onStart || function() {};
this.resultCallback = attrs.resultCallback || function() {};
this.clearStack = attrs.clearStack || function(fn) {fn();};
this.expectationFactory = attrs.expectationFactory;
this.expectationResultFactory = attrs.expectationResultFactory;
this.runnablesExplictlySetGetter = attrs.runnablesExplictlySetGetter || function() {};
this.throwOnExpectationFailure = !!attrs.throwOnExpectationFailure;
this.beforeFns = [];
this.afterFns = [];
this.beforeAllFns = [];
this.afterAllFns = [];
this.queueRunner = attrs.queueRunner || function() {};
this.disabled = false;
this.children = [];
@@ -46,6 +42,10 @@ getJasmineRequireObj().Suite = function() {
this.disabled = true;
};
Suite.prototype.pend = function(message) {
this.markedPending = true;
};
Suite.prototype.beforeEach = function(fn) {
this.beforeFns.unshift(fn);
};
@@ -71,6 +71,10 @@ getJasmineRequireObj().Suite = function() {
return 'disabled';
}
if (this.markedPending) {
return 'pending';
}
if (this.result.failedExpectations.length > 0) {
return 'failed';
} else {
@@ -78,51 +82,17 @@ getJasmineRequireObj().Suite = function() {
}
};
Suite.prototype.execute = function(onComplete) {
var self = this;
this.onStart(this);
if (this.disabled) {
complete();
return;
}
var allFns = [];
for (var i = 0; i < this.children.length; i++) {
allFns.push(wrapChildAsAsync(this.children[i]));
}
if (this.isExecutable()) {
allFns = this.beforeAllFns.concat(allFns);
allFns = allFns.concat(this.afterAllFns);
}
this.queueRunner({
queueableFns: allFns,
onComplete: complete,
userContext: this.sharedUserContext(),
onException: function() { self.onException.apply(self, arguments); }
});
function complete() {
self.result.status = self.status();
self.resultCallback(self.result);
if (onComplete) {
onComplete();
}
}
function wrapChildAsAsync(child) {
return { fn: function(done) { child.execute(done); } };
}
Suite.prototype.isExecutable = function() {
return !this.disabled;
};
Suite.prototype.isExecutable = function() {
var runnablesExplicitlySet = this.runnablesExplictlySetGetter();
return !runnablesExplicitlySet && hasExecutableChild(this.children);
Suite.prototype.canBeReentered = function() {
return this.beforeAllFns.length === 0 && this.afterAllFns.length === 0;
};
Suite.prototype.getResult = function() {
this.result.status = this.status();
return this.result;
};
Suite.prototype.sharedUserContext = function() {
@@ -138,6 +108,10 @@ getJasmineRequireObj().Suite = function() {
};
Suite.prototype.onException = function() {
if (arguments[0] instanceof j$.errors.ExpectationFailed) {
return;
}
if(isAfterAll(this.children)) {
var data = {
matcherName: '',
@@ -159,10 +133,17 @@ getJasmineRequireObj().Suite = function() {
if(isAfterAll(this.children) && isFailure(arguments)){
var data = arguments[1];
this.result.failedExpectations.push(this.expectationResultFactory(data));
if(this.throwOnExpectationFailure) {
throw new j$.errors.ExpectationFailed();
}
} else {
for (var i = 0; i < this.children.length; i++) {
var child = this.children[i];
child.addExpectationResult.apply(child, arguments);
try {
child.addExpectationResult.apply(child, arguments);
} catch(e) {
// keep going
}
}
}
};
@@ -175,17 +156,6 @@ getJasmineRequireObj().Suite = function() {
return !args[0];
}
function hasExecutableChild(children) {
var foundActive = false;
for (var i = 0; i < children.length; i++) {
if (children[i].isExecutable()) {
foundActive = true;
break;
}
}
return foundActive;
}
function clone(obj) {
var clonedObj = {};
for (var prop in obj) {

206
src/core/TreeProcessor.js Normal file
View File

@@ -0,0 +1,206 @@
getJasmineRequireObj().TreeProcessor = function() {
function TreeProcessor(attrs) {
var tree = attrs.tree,
runnableIds = attrs.runnableIds,
queueRunnerFactory = attrs.queueRunnerFactory,
nodeStart = attrs.nodeStart || function() {},
nodeComplete = attrs.nodeComplete || function() {},
orderChildren = attrs.orderChildren || function(node) { return node.children; },
stats = { valid: true },
processed = false,
defaultMin = Infinity,
defaultMax = 1 - Infinity;
this.processTree = function() {
processNode(tree, false);
processed = true;
return stats;
};
this.execute = function(done) {
if (!processed) {
this.processTree();
}
if (!stats.valid) {
throw 'invalid order';
}
var childFns = wrapChildren(tree, 0);
queueRunnerFactory({
queueableFns: childFns,
userContext: tree.sharedUserContext(),
onException: function() {
tree.onException.apply(tree, arguments);
},
onComplete: done
});
};
function runnableIndex(id) {
for (var i = 0; i < runnableIds.length; i++) {
if (runnableIds[i] === id) {
return i;
}
}
}
function processNode(node, parentEnabled) {
var executableIndex = runnableIndex(node.id);
if (executableIndex !== undefined) {
parentEnabled = true;
}
parentEnabled = parentEnabled && node.isExecutable();
if (!node.children) {
stats[node.id] = {
executable: parentEnabled && node.isExecutable(),
segments: [{
index: 0,
owner: node,
nodes: [node],
min: startingMin(executableIndex),
max: startingMax(executableIndex)
}]
};
} else {
var hasExecutableChild = false;
var orderedChildren = orderChildren(node);
for (var i = 0; i < orderedChildren.length; i++) {
var child = orderedChildren[i];
processNode(child, parentEnabled);
if (!stats.valid) {
return;
}
var childStats = stats[child.id];
hasExecutableChild = hasExecutableChild || childStats.executable;
}
stats[node.id] = {
executable: hasExecutableChild
};
segmentChildren(node, orderedChildren, stats[node.id], executableIndex);
if (!node.canBeReentered() && stats[node.id].segments.length > 1) {
stats = { valid: false };
}
}
}
function startingMin(executableIndex) {
return executableIndex === undefined ? defaultMin : executableIndex;
}
function startingMax(executableIndex) {
return executableIndex === undefined ? defaultMax : executableIndex;
}
function segmentChildren(node, orderedChildren, nodeStats, executableIndex) {
var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) },
result = [currentSegment],
lastMax = defaultMax,
orderedChildSegments = orderChildSegments(orderedChildren);
function isSegmentBoundary(minIndex) {
return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1;
}
for (var i = 0; i < orderedChildSegments.length; i++) {
var childSegment = orderedChildSegments[i],
maxIndex = childSegment.max,
minIndex = childSegment.min;
if (isSegmentBoundary(minIndex)) {
currentSegment = {index: result.length, owner: node, nodes: [], min: defaultMin, max: defaultMax};
result.push(currentSegment);
}
currentSegment.nodes.push(childSegment);
currentSegment.min = Math.min(currentSegment.min, minIndex);
currentSegment.max = Math.max(currentSegment.max, maxIndex);
lastMax = maxIndex;
}
nodeStats.segments = result;
}
function orderChildSegments(children) {
var specifiedOrder = [],
unspecifiedOrder = [];
for (var i = 0; i < children.length; i++) {
var child = children[i],
segments = stats[child.id].segments;
for (var j = 0; j < segments.length; j++) {
var seg = segments[j];
if (seg.min === defaultMin) {
unspecifiedOrder.push(seg);
} else {
specifiedOrder.push(seg);
}
}
}
specifiedOrder.sort(function(a, b) {
return a.min - b.min;
});
return specifiedOrder.concat(unspecifiedOrder);
}
function executeNode(node, segmentNumber) {
if (node.children) {
return {
fn: function(done) {
nodeStart(node);
queueRunnerFactory({
onComplete: function() {
nodeComplete(node, node.getResult());
done();
},
queueableFns: wrapChildren(node, segmentNumber),
userContext: node.sharedUserContext(),
onException: function() {
node.onException.apply(node, arguments);
}
});
}
};
} else {
return {
fn: function(done) { node.execute(done, stats[node.id].executable); }
};
}
}
function wrapChildren(node, segmentNumber) {
var result = [],
segmentChildren = stats[node.id].segments[segmentNumber].nodes;
for (var i = 0; i < segmentChildren.length; i++) {
result.push(executeNode(segmentChildren[i].owner, segmentChildren[i].index));
}
if (!stats[node.id].executable) {
return result;
}
return node.beforeAllFns.concat(result).concat(node.afterAllFns);
}
}
return TreeProcessor;
};

View File

@@ -1,6 +1,12 @@
getJasmineRequireObj().Any = function() {
getJasmineRequireObj().Any = function(j$) {
function Any(expectedObject) {
if (typeof expectedObject === 'undefined') {
throw new TypeError(
'jasmine.any() expects to be passed a constructor function. ' +
'Please pass one or use jasmine.anything() to match any object.'
);
}
this.expectedObject = expectedObject;
}
@@ -29,7 +35,7 @@ getJasmineRequireObj().Any = function() {
};
Any.prototype.jasmineToString = function() {
return '<jasmine.any(' + this.expectedObject + ')>';
return '<jasmine.any(' + j$.fnNameFor(this.expectedObject) + ')>';
};
return Any;

View File

@@ -4,11 +4,35 @@ getJasmineRequireObj().ObjectContaining = function(j$) {
this.sample = sample;
}
function getPrototype(obj) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
}
if (obj.constructor.prototype == obj) {
return null;
}
return obj.constructor.prototype;
}
function hasProperty(obj, property) {
if (!obj) {
return false;
}
if (Object.prototype.hasOwnProperty.call(obj, property)) {
return true;
}
return hasProperty(getPrototype(obj), property);
}
ObjectContaining.prototype.asymmetricMatch = function(other) {
if (typeof(this.sample) !== 'object') { throw new Error('You must provide an object to objectContaining, not \''+this.sample+'\'.'); }
for (var property in this.sample) {
if (!Object.prototype.hasOwnProperty.call(other, property) ||
if (!hasProperty(other, property) ||
!j$.matchersUtil.equals(this.sample[property], other[property])) {
return false;
}

10
src/core/errors.js Normal file
View File

@@ -0,0 +1,10 @@
getJasmineRequireObj().errors = function() {
function ExpectationFailed() {}
ExpectationFailed.prototype = new Error();
ExpectationFailed.prototype.constructor = ExpectationFailed;
return {
ExpectationFailed: ExpectationFailed
};
};

View File

@@ -167,11 +167,13 @@ getJasmineRequireObj().matchersUtil = function(j$) {
if (result) {
// Objects with different constructors are not equivalent, but `Object`s
// from different frames are.
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(isFunction(aCtor) && (aCtor instanceof aCtor) &&
isFunction(bCtor) && (bCtor instanceof bCtor))) {
return false;
// or `Array`s from different frames are.
if (className !== '[object Array]') {
var aCtor = a.constructor, bCtor = b.constructor;
if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
isFunction(bCtor) && bCtor instanceof bCtor)) {
return false;
}
}
// Deep compare objects.
for (var key in a) {

View File

@@ -14,6 +14,7 @@ getJasmineRequireObj().requireMatchers = function(jRequire, j$) {
'toEqual',
'toHaveBeenCalled',
'toHaveBeenCalledWith',
'toHaveBeenCalledTimes',
'toMatch',
'toThrow',
'toThrowError'

View File

@@ -0,0 +1,30 @@
getJasmineRequireObj().toHaveBeenCalledTimes = function(j$) {
function toHaveBeenCalledTimes() {
return {
compare: function(actual, expected) {
if (!j$.isSpy(actual)) {
throw new Error('Expected a spy, but got ' + j$.pp(actual) + '.');
}
var args = Array.prototype.slice.call(arguments, 0),
result = { pass: false };
if(!expected){
throw new Error('Expected times failed is required as an argument.');
}
actual = args[0];
var calls = actual.calls.count();
var timesMessage = expected === 1 ? 'once' : expected + ' times';
result.pass = calls === expected;
result.message = result.pass ?
'Expected spy ' + actual.and.identity() + ' not to have been called ' + timesMessage + '. It was called ' + calls + ' times.' :
'Expected spy ' + actual.and.identity() + ' to have been called ' + timesMessage + '. It was called ' + calls + ' times.';
return result;
}
};
}
return toHaveBeenCalledTimes;
};

View File

@@ -1,5 +1,5 @@
getJasmineRequireObj().toThrowError = function(j$) {
function toThrowError (util) {
function toThrowError () {
return {
compare: function(actual) {
var threw = false,
@@ -109,7 +109,7 @@ getJasmineRequireObj().toThrowError = function(j$) {
return expected === null && errorType === null;
},
matches: function(error) {
return (errorType === null || error.constructor === errorType) &&
return (errorType === null || error instanceof errorType) &&
(expected === null || messageMatch(error.message));
}
};

View File

@@ -2,7 +2,11 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
var jasmineRequire;
if (typeof module !== 'undefined' && module.exports) {
jasmineGlobal = global;
if (typeof global !== 'undefined') {
jasmineGlobal = global;
} else {
jasmineGlobal = {};
}
jasmineRequire = exports;
} else {
if (typeof window !== 'undefined' && typeof window.toString === 'function' && window.toString() === '[object GjsGlobal]') {
@@ -20,7 +24,8 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
jRequire.base(j$, jasmineGlobal);
j$.util = jRequire.util();
j$.Any = jRequire.Any();
j$.errors = jRequire.errors();
j$.Any = jRequire.Any(j$);
j$.Anything = jRequire.Anything(j$);
j$.CallTracker = jRequire.CallTracker();
j$.MockDate = jRequire.MockDate();
@@ -41,9 +46,11 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.SpyRegistry = jRequire.SpyRegistry(j$);
j$.SpyStrategy = jRequire.SpyStrategy();
j$.StringMatching = jRequire.StringMatching(j$);
j$.Suite = jRequire.Suite();
j$.Suite = jRequire.Suite(j$);
j$.Timer = jRequire.Timer();
j$.TreeProcessor = jRequire.TreeProcessor();
j$.version = jRequire.version();
j$.Order = jRequire.Order();
j$.matchers = jRequire.requireMatchers(jRequire, j$);

View File

@@ -11,6 +11,8 @@ jasmineRequire.HtmlReporter = function(j$) {
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
onRandomClick = options.onRandomClick || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
timer = options.timer || noopTimer,
results = [],
@@ -24,19 +26,17 @@ jasmineRequire.HtmlReporter = function(j$) {
this.initialize = function() {
clearPrior();
htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
createDom('div', {className: 'banner'},
createDom('a', {className: 'title', href: 'http://jasmine.github.io/', target: '_blank'}),
createDom('span', {className: 'version'}, j$.version)
createDom('div', {className: 'jasmine-banner'},
createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}),
createDom('span', {className: 'jasmine-version'}, j$.version)
),
createDom('ul', {className: 'symbol-summary'}),
createDom('div', {className: 'alert'}),
createDom('div', {className: 'results'},
createDom('div', {className: 'failures'})
createDom('ul', {className: 'jasmine-symbol-summary'}),
createDom('div', {className: 'jasmine-alert'}),
createDom('div', {className: 'jasmine-results'},
createDom('div', {className: 'jasmine-failures'})
)
);
getContainer().appendChild(htmlReporterMain);
symbols = find('.symbol-summary');
};
var totalSpecsDefined;
@@ -45,7 +45,7 @@ jasmineRequire.HtmlReporter = function(j$) {
timer.start();
};
var summary = createDom('div', {className: 'summary'});
var summary = createDom('div', {className: 'jasmine-summary'});
var topResults = new j$.ResultsNode({}, '', null),
currentParent = topResults;
@@ -81,8 +81,12 @@ jasmineRequire.HtmlReporter = function(j$) {
specsExecuted++;
}
if (!symbols){
symbols = find('.jasmine-symbol-summary');
}
symbols.appendChild(createDom('li', {
className: noExpectations(result) ? 'empty' : result.status,
className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
id: 'spec_' + result.id,
title: result.fullName
}
@@ -92,18 +96,18 @@ jasmineRequire.HtmlReporter = function(j$) {
failureCount++;
var failure =
createDom('div', {className: 'spec-detail failed'},
createDom('div', {className: 'description'},
createDom('div', {className: 'jasmine-spec-detail jasmine-failed'},
createDom('div', {className: 'jasmine-description'},
createDom('a', {title: result.fullName, href: specHref(result)}, result.fullName)
),
createDom('div', {className: 'messages'})
createDom('div', {className: 'jasmine-messages'})
);
var messages = failure.childNodes[1];
for (var i = 0; i < result.failedExpectations.length; i++) {
var expectation = result.failedExpectations[i];
messages.appendChild(createDom('div', {className: 'result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'stack-trace'}, expectation.stack));
messages.appendChild(createDom('div', {className: 'jasmine-result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
}
failures.push(failure);
@@ -114,57 +118,106 @@ jasmineRequire.HtmlReporter = function(j$) {
}
};
this.jasmineDone = function() {
var banner = find('.banner');
banner.appendChild(createDom('span', {className: 'duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
this.jasmineDone = function(doneResult) {
var banner = find('.jasmine-banner');
var alert = find('.jasmine-alert');
var order = doneResult && doneResult.order;
alert.appendChild(createDom('span', {className: 'jasmine-duration'}, 'finished in ' + timer.elapsed() / 1000 + 's'));
var alert = find('.alert');
banner.appendChild(
createDom('div', { className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom('div', { className: 'jasmine-payload' },
createDom('div', { className: 'jasmine-exceptions' },
createDom('input', {
className: 'jasmine-raise',
id: 'jasmine-raise-exceptions',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-raise-exceptions' }, 'raise exceptions')),
createDom('div', { className: 'jasmine-throw-failures' },
createDom('input', {
className: 'jasmine-throw',
id: 'jasmine-throw-failures',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-throw-failures' }, 'stop spec on expectation failure')),
createDom('div', { className: 'jasmine-random-order' },
createDom('input', {
className: 'jasmine-random',
id: 'jasmine-random-order',
type: 'checkbox'
}),
createDom('label', { className: 'jasmine-label', 'for': 'jasmine-random-order' }, 'run tests in random order'))
)
));
alert.appendChild(createDom('span', { className: 'exceptions' },
createDom('label', { className: 'label', 'for': 'raise-exceptions' }, 'raise exceptions'),
createDom('input', {
className: 'raise',
id: 'raise-exceptions',
type: 'checkbox'
})
));
var checkbox = find('#raise-exceptions');
var raiseCheckbox = find('#jasmine-raise-exceptions');
checkbox.checked = !env.catchingExceptions();
checkbox.onclick = onRaiseExceptionsClick;
raiseCheckbox.checked = !env.catchingExceptions();
raiseCheckbox.onclick = onRaiseExceptionsClick;
var throwCheckbox = find('#jasmine-throw-failures');
throwCheckbox.checked = env.throwingExpectationFailures();
throwCheckbox.onclick = onThrowExpectationsClick;
var randomCheckbox = find('#jasmine-random-order');
randomCheckbox.checked = env.randomTests();
randomCheckbox.onclick = onRandomClick;
var optionsMenu = find('.jasmine-run-options'),
optionsTrigger = optionsMenu.querySelector('.jasmine-trigger'),
optionsPayload = optionsMenu.querySelector('.jasmine-payload'),
isOpen = /\bjasmine-open\b/;
optionsTrigger.onclick = function() {
if (isOpen.test(optionsPayload.className)) {
optionsPayload.className = optionsPayload.className.replace(isOpen, '');
} else {
optionsPayload.className += ' jasmine-open';
}
};
if (specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
alert.appendChild(
createDom('span', {className: 'bar skipped'},
createDom('span', {className: 'jasmine-bar jasmine-skipped'},
createDom('a', {href: '?', title: 'Run all specs'}, skippedMessage)
)
);
}
var statusBarMessage = '';
var statusBarClassName = 'bar ';
var statusBarClassName = 'jasmine-bar ';
if (totalSpecsDefined > 0) {
statusBarMessage += pluralize('spec', specsExecuted) + ', ' + pluralize('failure', failureCount);
if (pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', pendingSpecCount); }
statusBarClassName += (failureCount > 0) ? 'failed' : 'passed';
statusBarClassName += (failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
} else {
statusBarClassName += 'skipped';
statusBarClassName += 'jasmine-skipped';
statusBarMessage += 'No specs found';
}
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage));
var seedBar;
if (order && order.random) {
seedBar = createDom('span', {className: 'jasmine-seed-bar'},
', randomized with seed ',
createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed)
);
}
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
for(i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
var errorBarMessage = 'AfterAll ' + failedSuite.failedExpectations[j].message;
var errorBarClassName = 'bar errored';
var errorBarClassName = 'jasmine-bar jasmine-errored';
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessage));
}
}
var results = find('.results');
var results = find('.jasmine-results');
results.appendChild(summary);
summaryList(topResults, summary);
@@ -174,8 +227,8 @@ jasmineRequire.HtmlReporter = function(j$) {
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (resultNode.type == 'suite') {
var suiteListNode = createDom('ul', {className: 'suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'suite-detail'},
var suiteListNode = createDom('ul', {className: 'jasmine-suite', id: 'suite-' + resultNode.result.id},
createDom('li', {className: 'jasmine-suite-detail'},
createDom('a', {href: specHref(resultNode.result)}, resultNode.result.description)
)
);
@@ -184,8 +237,8 @@ jasmineRequire.HtmlReporter = function(j$) {
domParent.appendChild(suiteListNode);
}
if (resultNode.type == 'spec') {
if (domParent.getAttribute('class') != 'specs') {
specListNode = createDom('ul', {className: 'specs'});
if (domParent.getAttribute('class') != 'jasmine-specs') {
specListNode = createDom('ul', {className: 'jasmine-specs'});
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
@@ -197,7 +250,7 @@ jasmineRequire.HtmlReporter = function(j$) {
}
specListNode.appendChild(
createDom('li', {
className: resultNode.result.status,
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom('a', {href: specHref(resultNode.result)}, specDescription)
@@ -209,24 +262,24 @@ jasmineRequire.HtmlReporter = function(j$) {
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'menu bar spec-list'},
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
createDom('span', {}, 'Spec List | '),
createDom('a', {className: 'failures-menu', href: '#'}, 'Failures')));
createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures')));
alert.appendChild(
createDom('span', {className: 'menu bar failure-list'},
createDom('a', {className: 'spec-list-menu', href: '#'}, 'Spec List'),
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'},
createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'),
createDom('span', {}, ' | Failures ')));
find('.failures-menu').onclick = function() {
setMenuModeTo('failure-list');
find('.jasmine-failures-menu').onclick = function() {
setMenuModeTo('jasmine-failure-list');
};
find('.spec-list-menu').onclick = function() {
setMenuModeTo('spec-list');
find('.jasmine-spec-list-menu').onclick = function() {
setMenuModeTo('jasmine-spec-list');
};
setMenuModeTo('failure-list');
setMenuModeTo('jasmine-failure-list');
var failureNode = find('.failures');
var failureNode = find('.jasmine-failures');
for (var i = 0; i < failures.length; i++) {
failureNode.appendChild(failures[i]);
}
@@ -284,6 +337,10 @@ jasmineRequire.HtmlReporter = function(j$) {
return addToExistingQueryString('spec', result.fullName);
}
function seedHref(seed) {
return addToExistingQueryString('seed', seed);
}
function defaultQueryString(key, value) {
return '?' + key + '=' + value;
}

View File

@@ -14,6 +14,7 @@ $failing-color: #ca3a11;
$pending-color: #ba9d37;
$empty-color: #eff543;
$neutral-color: #bababa;
$jasmine-color: #8a4182;
$font-size: 11px;
$large-font-size: 14px;
@@ -45,23 +46,23 @@ body {
line-height: $line-height;
}
.banner,
.symbol-summary,
.summary,
.result-message,
.spec .description,
.spec-detail .description,
.alert .bar,
.stack-trace {
.jasmine-banner,
.jasmine-symbol-summary,
.jasmine-summary,
.jasmine-result-message,
.jasmine-spec .jasmine-description,
.jasmine-spec-detail .jasmine-description,
.jasmine-alert .jasmine-bar,
.jasmine-stack-trace {
padding-left: $margin-unit - 5px;
padding-right: $margin-unit - 5px;
}
.banner {
.jasmine-banner {
position: relative;
}
.banner .title {
.jasmine-banner .jasmine-title {
background: inline-image('jasmine-horizontal.png') no-repeat;
background: inline-image('jasmine-horizontal.svg') no-repeat, none;
@include background-size(100%);
@@ -71,18 +72,12 @@ body {
height: 25px;
}
.banner .version {
.jasmine-banner .jasmine-version {
margin-left: $margin-unit;
position: relative;
top: 6px;
}
.banner .duration {
position: absolute;
right: 14px;
top: 6px;
}
// This div is available for testing elements that must be added to the DOM.
// We position it out of view, so it doesn't obstruct the runner.
#jasmine_content {
@@ -90,35 +85,37 @@ body {
right: 100%;
}
.version {
.jasmine-version {
color: $faint-text-color;
}
//--- Banner ---//
.banner {
.jasmine-banner {
margin-top: $line-height;
}
.duration {
color: $faint-text-color;
.jasmine-duration {
color: #fff;
float: right;
line-height: $line-height * 2;
padding-right: 9px;
}
//--- Symbol summary ---//
.symbol-summary {
.jasmine-symbol-summary {
@include clearfix;
margin: $line-height 0;
li {
display: inline-block;
height: ($line-height / 2) + 1;
height: ($line-height / 2) + 3;
width: $line-height;
font-size: 16px;
&.passed {
&.jasmine-passed {
font-size: 14px;
&:before {
@@ -127,7 +124,7 @@ body {
}
}
&.failed {
&.jasmine-failed {
line-height: ($line-height / 2) + 2;
&:before {
@@ -138,7 +135,7 @@ body {
}
}
&.disabled {
&.jasmine-disabled {
font-size: 14px;
&:before {
@@ -147,7 +144,7 @@ body {
}
}
&.pending {
&.jasmine-pending {
line-height: 17px;
&:before {
color: $pending-color;
@@ -155,7 +152,7 @@ body {
}
}
&.empty {
&.jasmine-empty {
font-size: 14px;
&:before {
@@ -166,39 +163,60 @@ body {
}
}
.exceptions {
color: #fff;
.jasmine-run-options {
float: right;
margin-top: 5px;
margin-right: 5px;
border: 1px solid $jasmine-color;
color: $jasmine-color;
position: relative;
line-height: 20px;
.jasmine-trigger {
cursor: pointer;
padding: 8px 16px;
}
.jasmine-payload {
position: absolute;
display: none;
right: -1px;
border: 1px solid $jasmine-color;
background-color: $page-background-color;
white-space: nowrap;
padding: 4px 8px;
&.jasmine-open {
display: block;
}
}
}
//--- Alerts: status bars ---//
.bar {
.jasmine-bar {
line-height: $line-height * 2;
font-size: $large-font-size;
display: block;
color: #eee;
&.failed {
&.jasmine-failed {
background-color: $failing-color;
}
&.passed {
&.jasmine-passed {
background-color: $passing-color;
}
&.skipped {
&.jasmine-skipped {
background-color: $neutral-color;
}
&.errored {
&.jasmine-errored {
background-color: $failing-color;
}
&.menu {
&.jasmine-menu {
background-color: #fff;
color: $faint-text-color;
@@ -213,65 +231,29 @@ body {
}
// simplify toggle control between the two menu bars
&.spec-list {
.bar.menu.failure-list,
.results .failures {
&.jasmine-spec-list {
.jasmine-bar.jasmine-menu.jasmine-failure-list,
.jasmine-results .jasmine-failures {
display: none;
}
}
&.failure-list {
.bar.menu.spec-list,
.summary {
&.jasmine-failure-list {
.jasmine-bar.jasmine-menu.jasmine-spec-list,
.jasmine-summary {
display: none;
}
}
.running-alert {
background-color: $light-text-color;
}
//--- Results ---//
.results {
.jasmine-results {
margin-top: $line-height;
}
//--- Results menu ---//
&.showDetails {
.summaryMenuItem {
font-weight: normal;
text-decoration: inherit;
&:hover {
text-decoration: underline;
}
}
.detailsMenuItem {
font-weight: bold;
text-decoration: underline;
}
.summary {
display: none;
}
#details {
display: block;
}
}
.summaryMenuItem {
font-weight: bold;
text-decoration: underline;
}
//--- Results summary: Suites and Specs names/links ---//
.summary {
.jasmine-summary {
margin-top: $margin-unit;
ul {
@@ -280,36 +262,40 @@ body {
padding-top: 0;
padding-left: 0;
&.suite {
&.jasmine-suite {
margin-top: $margin-unit/2;
margin-bottom: $margin-unit/2
}
}
li {
&.passed a {
&.jasmine-passed a {
color: $passing-color;
}
&.failed a {
&.jasmine-failed a {
color: $failing-color;
}
&.empty a {
&.jasmine-empty a {
color: $pending-color;
}
&.pending a {
&.jasmine-pending a {
color: $pending-color;
}
&.jasmine-disabled a {
color: $neutral-color;
}
}
}
.description+.suite {
.jasmine-description + .jasmine-suite {
margin-top: 0;
}
.suite {
.jasmine-suite {
margin-top: $margin-unit;
a {
@@ -319,11 +305,11 @@ body {
//--- Failure details ---//
.failures {
.spec-detail {
.jasmine-failures {
.jasmine-spec-detail {
margin-bottom: $line-height * 2;
.description {
.jasmine-description {
background-color: $failing-color;
a {
@@ -333,7 +319,7 @@ body {
}
}
.result-message {
.jasmine-result-message {
padding-top: $line-height;
color: $text-color;
@@ -341,11 +327,11 @@ body {
white-space: pre;
}
.result-message span.result {
.jasmine-result-message span.jasmine-result {
display: block;
}
.stack-trace {
.jasmine-stack-trace {
margin: 5px 0 0 0;
max-height: $line-height * 16;
overflow: auto;

View File

@@ -2,10 +2,8 @@
if [ $USE_SAUCE == true ]
then
if [ $TRAVIS_SECURE_ENV_VARS == true ]
if [ $TRAVIS_SECURE_ENV_VARS != true ]
then
curl -L https://gist.github.com/santiycr/5139565/raw/sauce_connect_setup.sh | bash
else
echo "skipping tests since we can't use sauce"
exit 0
fi

View File

@@ -1,6 +1,4 @@
#!/bin/bash -e
npm install -g grunt-cli
npm install
grunt jshint execSpecsInNode
npm test