Compare commits

...

601 Commits

Author SHA1 Message Date
Steve Gravrock
e86a7f00a6 Bump version to 3.10.1 2021-10-22 16:15:54 -07:00
Jan Molak
504ef27899 Fixed result.pendingReason for specs marked with xit. Closes #1939 2021-10-22 14:12:28 -07:00
Steve Gravrock
572452a15a Added supported environments to 3.10.0 release notes 2021-10-13 16:47:48 -07:00
Steve Gravrock
896412367a Bump version to 3.10.0 2021-10-13 15:46:21 -07:00
Steve Gravrock
503a7409f0 Merge branch 'issue-1854-asyncerror' of https://github.com/AndreWillomitzer/jasmine into main
* Improves error message when an async expectation occurs after the spec
  finishes
* Merges #1937 from @AndreWillomitzer
* Fixes #1854
2021-10-12 17:15:53 -07:00
Andre Willomitzer
bb9175cb66 added additional error msg for delayedExpectation
added matching error msgs in jasmine objects

Ran prettier.

removed indenting, formatted column length < 80
2021-10-12 13:17:24 -04:00
Steve Gravrock
469b557828 Merge branch 'fix/ie' of https://github.com/nicojs/jasmine into main
* Merges #1936 from @nicojs
2021-10-07 10:17:16 -07:00
Nico Jansen
503715c275 test(ie): refactor promises to callbacks 2021-10-07 10:23:52 +02:00
Steve Gravrock
4482355885 Removed jsdoc entry for SpecResult#trace
Deferred to 4.0.
2021-10-06 11:31:29 -07:00
Steve Gravrock
6542364381 Merge branch 'feat/support-multiple-runs' of https://github.com/nicojs/jasmine into main
* Merges #1934 from @nicojs
* Fixes #1925
2021-10-06 11:20:34 -07:00
Nico Jansen
1fc911e0fa Support running jasmine multiple times
Add support for running jasmine multiple times.

```js
const Jasmine = require('jasmine');

async function main() {
  const jasmine = new Jasmine({ projectBaseDir: process.cwd() });
  let specId = 'spec0';
  jasmine.loadConfigFile('./spec/support/jasmine.json');
  jasmine.env.configure({
    specFilter(sp) {
      return sp.id === specId;
    },
    autoCleanClosures: false
  });
  jasmine.exit = () => {};
  await jasmine.execute();
  specId = 'spec2';
  await jasmine.execute();
}

main().catch((err) => {
  console.error(err);
  process.exitCode = 1;
});
```

With `jasmine.env.configure({ autoCleanClosures: false })` you disable Jasmine's feature to automatically clean closures (functions) during the test run. This is a requirement to be able to rerun.

When `execute` is called more than once, the `topSuite.reset` is called, which will reset the state for the next run as well as reset any child suites.

Add a function `exclude` to the `Suite` and `Spec` clases. This functions similar to `pend`, but will allow the "pending" state to persist over multiple runs. This is useful when `xit` is used.

Revert changes to jasmine.js

fix: make sure to call hooks during second run

Remove jsdoc from private apis

Fix elint issue

Add new line
2021-10-06 20:12:45 +02:00
Steve Gravrock
fdad8849df Revert "Added the ability to associate trace information with failing specs"
Pushing this back to 4.0 in hopes of increasing the chance that third
party reporters will notice it and add support.

This reverts commit 7a289f1de7.
2021-10-02 09:45:15 -07:00
Steve Gravrock
7a289f1de7 Added the ability to associate trace information with failing specs
This is meant to aid in debugging failures, particularly intermittent
failures, in cases where interactive debugging or console.log aren't
suitable.
2021-09-25 16:19:28 -07:00
Steve Gravrock
ef981bb794 Run the browser-flakes build on the debugging branch 2021-09-25 15:50:34 -07:00
Steve Gravrock
c3fb3e985a Reject timeout values that are too large for setTimeout
See #1930
2021-09-25 15:43:31 -07:00
Steve Gravrock
7fc3408051 Expanded jsdocs for jasmine.DEFAULT_TIMEOUT_INTERVAL 2021-09-25 13:29:44 -07:00
Steve Gravrock
af1b43eeff Merge branch 'patch-1' of https://github.com/trusktr/jasmine into main
* Merges #1931 from @trusktr
* Adds discussion of max timeout value to jsdocs
2021-09-25 13:28:34 -07:00
Steve Gravrock
4c043717a9 Revert "Dogfood the new jasmine-npm completion interface"
This works, but until the -npm 3.10.0 is out, it creates a chicken and egg
problem where each of core 3.10.0 and -npm 3.10.0 needs to be released
after the other.

This reverts commit 1c9382c990.
2021-09-25 12:11:20 -07:00
Steve Gravrock
40be00310d Don't immediately move to the next queueable fn on async error
This allows assertion failures and other errors that occcur after the async
error to be routed to the correct spec/suite.

Previously, Jasmine treated global errors and unhandled promise rejections
just like exceptions thrown from a synchronous spec: it recorded the error
as a spec failure and moved on. Now, global errors and uhandled rejections
are recorded as failures but the current queueable fn will continue until
it either signals completion or times out. Global errors and unhandled
rejections are different from synchronous exceptions: it's common for the
queueable fn that caused them to continue executing. Immediately moving on
often meant that the queueable fn would produce expectation failures or
other errors when a different spec or suite was running, thus causing
those failures to be routed to the wrong place.
2021-09-24 11:22:04 -07:00
Steve Gravrock
1f318c3c93 Added missing @since annotations 2021-09-23 13:38:52 -07:00
Steve Gravrock
be29aa95eb Improved jsdocs for asymmetric equality testers 2021-09-23 11:59:20 -07:00
Steve Gravrock
e3c9a59c6c Added a stringContaining asymmetric equality tester
* Fixes #1923.
2021-09-22 11:28:24 -07:00
Joe Pea
b312ed4940 update base.js docs, mention setting DEFAULT_TIMEOUT_INTERVAL to a high number while debugging
This info is useful because if someone does not set the number to a high enough value while stepping through test code, before or after hooks may be triggered mid-test while the user is debugging which will be confusing.
2021-09-21 21:39:21 -07:00
Steve Gravrock
00f6708e1f Removed unused submodule 2021-09-18 09:43:02 -07:00
Steve Gravrock
3a47a3bd04 Fixed flaky spec 2021-09-06 15:35:37 -07:00
Steve Gravrock
1c9382c990 Dogfood the new jasmine-npm completion interface 2021-09-04 13:39:17 -07:00
Steve Gravrock
394be99832 Fixed sass deprecation warnings
See <https://sass-lang.com/documentation/breaking-changes/slash-div>.
[#179260511]
2021-09-03 15:51:51 -07:00
Steve Gravrock
62a667a8e3 Added a deprecation notice to the gem's description
[#179330717]
2021-08-30 18:37:31 -07:00
Steve Gravrock
d277827d5e Fixed typo in 3.9.0 release notes 2021-08-21 19:09:01 -07:00
Steve Gravrock
644c175338 Print a deprecation message when the jasmine-core gem is loaded
[#179247158]
[#179247160]
2021-08-21 18:35:38 -07:00
Steve Gravrock
a6d7eb2a06 Bump version to 3.9.0 2021-08-21 12:00:23 -07:00
Steve Gravrock
dd8a65cb60 Better reporting of unhandled promise rejections with truthy but non-Error reasons on Node
[#179227413]
2021-08-14 14:03:03 -07:00
Steve Gravrock
e72d161fab Return a promise from Env#execute in environments that support promises
[#178373231]
2021-08-07 13:05:55 -07:00
Steve Gravrock
dcaac62a6c Updated deprecaton messages for Env#throwOnExpectationFailure() and Env#stopOnSpecFailure() 2021-07-31 08:02:39 -07:00
Steve Gravrock
b696bec9e3 Renamed failFast and oneFailurePerSpec config props to stopOnSpecFailure and stopSpecOnExpectationFailure
The new names are more self-explanatory and consistent with jasmine-npm. The
old names are deprecated but still work.

[#178682783]
2021-07-31 07:51:50 -07:00
Steve Gravrock
43073b3bc5 Added API docs for Suite#id and Spec#id
These properties are the only way to obtain runnable IDs, without which
you can't call the form of Env#execute that takes an array of IDs.
2021-07-29 19:32:15 -07:00
Steve Gravrock
286524959b Split boot.js in two to allow the env to be configured in between
This is mainly intended to support jasmine-browser-runner, which will load
a script that configures the env in between the two boot files (boot0.js and
boot1.js). The single-file boot.js is retained for now but will be removed
in a future release.
2021-07-26 18:05:36 -07:00
Steve Gravrock
2c32dd5703 Run browser-flakes build before regular cron build 2021-07-20 17:57:54 -07:00
Steve Gravrock
c1d1d69be2 Fixed test failures in Chrome and Edge 2021-07-19 12:08:40 -07:00
Steve Gravrock
3513249d73 Built distribution 2021-07-19 12:08:18 -07:00
Steve Gravrock
21bfbbb721 Merge branch 'iserror-tt' of https://github.com/bjarkler/jasmine into main
* Fixes Trusted Types error in Chromium-based browsers
* Merges #1921 from @bjarkler
* Fixes #1910
2021-07-19 12:06:12 -07:00
Steve Gravrock
88b90ec258 Backfilled unit tests for j$.isError_ 2021-07-19 10:31:53 -07:00
Steve Gravrock
50c88e7774 Mark Env#hideDisabled deprecated in jsdocs 2021-07-08 18:53:21 -07:00
Steve Gravrock
3e64ce3310 Removed property tests for MatchersUtil#equals
These might be useful for a function with a more restricted domain. But for
equals, which accepts two of literally anything, the short run was too short
to catch any problems and the long run tended to exceed the CircleCi timeout.
2021-07-03 08:37:15 -07:00
Steve Gravrock
00586e50e0 Bump version to 3.8.0 2021-07-01 17:06:14 -07:00
Bjarki
dc80a282ba Make j$.isError_ compatible with Trusted Types
The isError_ check uses a heuristic that calls the Function constructor
to determine if the given value is an Error object. This results in a
runtime violation in test suites that enforce Trusted Types.

Since Trusted Types are only supported in modern browsers (currently,
Chromium-based browsers), we can use a more straightforward heuristic in
environments where Trusted Types are supported.

Fixes #1910. See that thread for more details.
2021-07-01 20:21:44 +00:00
Steve Gravrock
27c650ec08 Updated package description 2021-06-30 17:10:51 -07:00
Steve Gravrock
56daa6f461 Merge branch 'select-spec' of https://github.com/jlpstolwijk/jasmine into main
* Merges #1920 from @jlpstolwijk
* Fixes spec filtering in Karma
* Fixes #1906
2021-06-29 17:10:06 -07:00
Joris Stolwijk
e4c7d8af45 new attempt for fixing #1906: add window.location.pathname to hrefs + comments + fixed tests 2021-06-29 14:03:25 +02:00
Steve Gravrock
ee88ecc614 Revert "add url pathName in toQueryString function - fixes (https://github.com/jasmine/jasmine/issues/1906 ) + comment + test"
Reverted because it breaks the option checkboxes in the HTML reporter, both
in the standalone distribution and in jasmine-browser-runner.

Reopens #1906.

This reverts commit 1e4f0d1545.
2021-06-28 12:42:05 -07:00
Steve Gravrock
ec038273f1 Updated contributing guide
* Removed outdated steps
* Replaced list of environments with a pointer to the README
* Misc copy edits
2021-06-26 11:33:03 -07:00
Steve Gravrock
c5bdd79a1e Added TS typings and jasmine-browser-runner to issue template 2021-06-26 11:21:19 -07:00
Steve Gravrock
dbc1a0aa56 Added expectAsync(...).already
* Causes async matchers to immediately fail if the promise is pending
* Fixes #1845
2021-06-23 20:13:01 -07:00
Steve Gravrock
5862b22aef Include rejection details in failure messages for toBeResolved and toBeResolvedWith
[#178559119]
2021-06-21 16:43:51 -07:00
Steve Gravrock
163f93d6ff Removed constructors from jsdocs of classes that aren't user-constructable 2021-06-21 14:19:31 -07:00
Steve Gravrock
1893bf6c16 Added jsdocs for asymmetric equality testers 2021-06-21 14:09:14 -07:00
Steve Gravrock
095745ab12 Removed gulp-jasmine-browser mention from README 2021-06-21 13:31:28 -07:00
Steve Gravrock
68db3f6fcf Merge branch 'select-spec' of https://github.com/jlpstolwijk/jasmine into main
* Merges #1907 from @jlpstolwijk
* Fixes #1906
* Fixes spec filtering in karma-jasmine-html-reporter
2021-06-14 17:59:29 -07:00
Joris Stolwijk
1e4f0d1545 add url pathName in toQueryString function - fixes (https://github.com/jasmine/jasmine/issues/1906 ) + comment + test 2021-06-14 15:05:12 +02:00
Steve Gravrock
c546d2cb6d Merge branch 'patch-1' of https://github.com/eltociear/jasmine into main
* Fixes typo in spec name
* Merges #1918 from @eltociear
2021-06-13 09:57:23 -07:00
Steve Gravrock
6e097528f5 Include only specified files in the NPM package 2021-06-13 09:52:01 -07:00
Ikko Ashimine
4e1f36cbb0 Fix typo in SpySpec.js
ommitted -> omitted
2021-06-12 10:00:36 +09:00
Steve Gravrock
0aee81cfb9 Remvoed checks for typed array support in the test suite
All supported browsers have all typed arrays except for Uint8ClampedArray,
BigInt64Array, and BigUint64Array.
2021-06-05 13:31:26 -07:00
Steve Gravrock
1e50b49092 Fixed test failures on IE 10 2021-06-05 13:13:46 -07:00
Steve Gravrock
6aecf16cde Test coverage for MatchersUtil#equals with typed arrays 2021-06-05 12:03:11 -07:00
Steve Gravrock
f2de1be96a Fixed "stop spec on expectation failure" checkbox in standalone
Fixes [#178248968].
2021-06-01 08:49:34 -07:00
Steve Gravrock
5f4a1c4276 Merge branch 'issue/1897' of https://github.com/Dari-K/jasmine into main
* Adds option for spyOnAllFunctions to include non-enumerable props
* Merges #1909 from @Dari-k
* Fixes #1897
2021-05-26 17:44:54 -07:00
Darius Keeley
a4ef3687ee Add optional param to spyOnAllFunctions to include non-enumerable properties 2021-05-25 11:37:24 +01:00
Steve Gravrock
9065b4c3b7 Added a jsdoc cross-reference from Configuration to its usage 2021-05-21 17:13:07 -07:00
Steve Gravrock
140225e7c3 Isolate specs that are flaky in browsers
* Don't run them in browsers in the regular CI build
* Run them in browsers in a special nightly build
* Run them in Node in the regular CI build
* Run them when developers manually run the suite

This should allow the regular CI build to give us a more useful signal,
while keeping us from losing sight of the flaky specs.
2021-05-15 07:44:25 -07:00
Steve Gravrock
8b38389d56 Test against Node 16
* Replaced node-sass dependency that isn't compatible with Node 16
* Added Node 16 to CI matrix
* Fixes #1894
2021-05-13 17:18:57 -07:00
Steve Gravrock
b7c2a2f6fb Removed unused dev dependencies 2021-05-13 12:52:44 -07:00
Steve Gravrock
c5d4a40219 Deprecated Python 2021-05-08 12:06:49 -07:00
Steve Gravrock
c7c8b6b93e Added Chrome back to CI browser list 2021-05-04 17:24:06 -07:00
Steve Gravrock
8a42437059 Added a note about testing on Windows to the releasing instructions 2021-05-04 09:28:35 -07:00
Steve Gravrock
cacc6f4278 Skip the middle Safari versions to speed up CI 2021-04-24 15:07:23 -07:00
Steve Gravrock
d815e99456 Added jsdocs for Spy.callData.returnValue 2021-04-24 14:57:33 -07:00
Steve Gravrock
5e3f937221 Added a note about correct usage of async matchers 2021-04-24 12:43:25 -07:00
Steve Gravrock
d666f1efbb Run browser tests on push, except for PRs 2021-04-23 08:39:02 -07:00
Steve Gravrock
4515b76f07 Run browser tests on all non-PR branches 2021-04-23 08:37:29 -07:00
Steve Gravrock
0897e31a2d Run cron builds on 3.99 and 4.0 branches 2021-04-23 08:37:18 -07:00
Steve Gravrock
9555cb9842 Pass Sauce tunnel identifier correctly 2021-04-17 16:14:45 -07:00
Steve Gravrock
d6fa9dd1a0 Fixed jsdocs for Spy#calls#thisFor 2021-04-17 12:32:59 -07:00
Steve Gravrock
25fbe0646a Merge branch 'spy-calls-thisFor' of https://github.com/ajvincent/jasmine into main
* Merges #1903 from @ajvincent
* Adds Spy#calls#thisFor
2021-04-17 12:14:41 -07:00
Steve Gravrock
316ce1e2d3 Updated contributing guide etc. 2021-04-17 11:54:11 -07:00
Steve Gravrock
82cc1083b6 Migrated from Travis to Circle CI 2021-04-17 11:34:56 -07:00
Steve Gravrock
c2f04ba627 Further compensate for clock jitter 2021-04-17 11:34:56 -07:00
Steve Gravrock
97a46f4560 Fixed test failures on Safari 8 and 9 2021-04-17 11:34:56 -07:00
Steve Gravrock
113134cdbd Fixed test failure in Firefox 68 ESR 2021-04-17 11:34:56 -07:00
Steve Gravrock
dad5f5fd6b Fixed test failure in Safari 8 2021-04-17 11:34:53 -07:00
Alexander J. Vincent
fa72544974 CallTracker.thisFor(): add test for undefined context object. 2021-04-13 18:35:04 -07:00
Alexander J. Vincent
e303de52ed Implement CallTracker.thisFor(). 2021-04-11 22:59:43 -07:00
Steve Gravrock
5f9315731e Improved handling of unhandled promise rejections with no error in Node
* Fixes #1759
2021-04-06 18:48:56 -07:00
Steve Gravrock
ce850c472a API docs for Env#topSuite and Suite 2021-04-03 11:09:30 -07:00
Steve Gravrock
2fc5182ddc Added missing jsdocs
* Env#execute
* Env#allowRespy
* Enough of Spec to support spec filters
2021-03-31 18:16:58 -07:00
Steve Gravrock
6be2102b64 Built distribution 2021-03-26 17:27:14 -07:00
Steve Gravrock
c6a79d3ab7 Merge branch 'patch-2' of https://github.com/UziTech/jasmine into main
* Merges #1892 from @UziTech
* Fixes config.seed type in jsdocs
2021-03-26 17:25:30 -07:00
Tony Brix
3f232fba80 docs: seed can be number or string 2021-03-26 00:10:15 -05:00
Tony Brix
cde6ea79a3 docs: fix jsdoc seed type 2021-03-25 22:05:02 -05:00
Steve Gravrock
0782a73a98 Merge branch 'array_buffer' of https://github.com/Finesse/jasmine into main
* Adds support for ArrayBuffers to matchersUtil.equals
* Merges #1891 from @Finesse
* Merges #1689 from @dankurka
* Fixes #1687
2021-03-22 13:06:40 -07:00
Surgie Finesse
37073e2768 Fix the review notices 2021-03-22 19:26:33 +10:00
Surgie Finesse
f7f928fdd3 Merge remote-tracking branch 'upstream/main' into array_buffer
# Conflicts:
#	spec/core/matchers/matchersUtilSpec.js
2021-03-22 18:33:50 +10:00
Steve Gravrock
503b653a10 Travis browser matrix updates
* Added latest Safari
* Added the Firefox version that's closest to current ESR
2021-03-21 11:30:21 -07:00
Steve Gravrock
cb044aa273 Bump version to 3.7.1 2021-03-18 17:28:04 -07:00
Steve Gravrock
5c17456925 Updated release instructions 2021-03-17 19:44:16 -07:00
Steve Gravrock
592fba22b8 Bump version to 3.7.0 2021-03-17 18:38:34 -07:00
Steve Gravrock
58ef707bc6 Added jasmine.isSpy to the public interface
* Fixes #1880
2021-03-17 17:58:51 -07:00
Steve Gravrock
050c1f051c Fixed intermittent test failures 2021-03-14 12:23:17 -07:00
Steve Gravrock
8d0c52e2ec Temporarily removed global error handler stack validation
This fails somewhat frequently (every 2-4 runs of Jasmine's own test
suite) on Safari. Until we get to the bottom of that, it's removed.
2021-03-14 11:46:23 -07:00
Steve Gravrock
de91427356 Fixed instructions for running Jasmine's ci script 2021-03-14 11:43:38 -07:00
Steve Gravrock
324bc201c2 Built distribution 2021-03-13 13:52:10 -08:00
Steve Gravrock
76f34e90dc Allow custom object formatters to be added in beforeAll
Fixes #1876.
2021-03-13 13:49:30 -08:00
Steve Gravrock
46e7158c77 Removed unused util.htmlEscape 2021-03-04 12:46:23 -08:00
Steve Gravrock
9ab039e330 Merge branch 'expectAllTruthyAndFalsy' of https://github.com/yasinkocak/jasmine into main
* Merges #1875 from @yasinkocak
* Adds additional assertions to tests for toBeTruthy and toBeFalsy
2021-02-27 10:31:31 -08:00
Yasin Kocak
3f5c47dff3 expect all truthy and falsy 2021-01-02 10:55:14 +01:00
Steve Gravrock
1320b0614f Merge branch 'use-global-onerror' into main
* Merges #1860 from @greghuc
* Allows specs to disable Jasmine's global error handling by overwriting
  `onerror`.
2020-11-24 11:13:24 -08:00
Gregory Huczynski
905e3fc3f9 Enable custom promise error handling through overriding of global.onerror 2020-11-24 11:04:04 -08:00
Steve Gravrock
89331bb1bb Fixed comparison between URL objects
* Fixes #1866
2020-11-21 13:47:44 -08:00
Steve Gravrock
88de272c89 Merge branch 'main' of https://github.com/JannesMeyer/jasmine into main
* Merges #1862 from @JannesMeyer
* Adds support for stack traces created by `node --enable-source-maps`
  with tools like the Typescript compiler.
2020-11-09 12:15:37 -08:00
Jannes Meyer
60bbe68148 Support source maps 2020-11-05 11:40:04 +01:00
Steve Gravrock
623e638cd4 Updated supported Node versions in README 2020-11-02 16:26:55 -08:00
Steve Gravrock
b1bcd6e825 Pointed Travis badge at travis-ci.com, not .org 2020-10-29 15:10:54 -07:00
Steve Gravrock
204acf7297 Updated Node versions in .travis.yml 2020-10-20 14:14:24 -07:00
Steve Gravrock
cd1131354b Merge branch 'enumerable' of https://github.com/DCtheTall/jasmine into main
* Merges #1859 from DCtheTall
* Fixes #1837
2020-10-10 18:01:48 -07:00
Steve Gravrock
c24aef15b1 Built distribution 2020-10-10 18:00:09 -07:00
DCtheTall
d5d5d1965f Have properties added by createSpyObj() be enumerable. 2020-10-02 13:49:34 -04:00
Steve Gravrock
d27bb8fa96 Run Prettier on all files 2020-09-29 18:05:38 -07:00
Steve Gravrock
7d5ca27b9d Check for forgotten console and debugger statements 2020-09-17 13:33:25 -07:00
Steve Gravrock
795651d3b6 Removed debugger statements 2020-09-13 13:40:15 -07:00
Steve Gravrock
e7daa429a1 Show the name of the spec/suite that caused a deprecation 2020-09-13 12:59:25 -07:00
Steve Gravrock
51ad18cb28 Warn if a runable both takes a callback and returns a promise 2020-09-13 12:47:24 -07:00
Steve Gravrock
0b81705c11 Detect global error handler stack corruption 2020-09-02 14:43:17 -07:00
Steve Gravrock
00feef8632 Fixed global error handler stack corruption in Jasmine's own tests 2020-09-02 14:01:57 -07:00
Steve Gravrock
5a715aecee Removed unnecessary console.log 2020-09-01 15:25:44 -07:00
Steve Gravrock
8cb44582bc Don't overwrite MatchersUtil methods with ones that were added to Array.prototype, esp. contains
Fixes #1849.
2020-09-01 15:18:53 -07:00
Steve Gravrock
53d8073707 Allow generator functions to be passed to .and.callFake
Fixes #1848.
2020-08-29 13:15:14 -07:00
Steve Gravrock
e0eb4755cb Merge branch 'fix-to-be-pending-typo' of https://github.com/SnailCoil/jasmine into main
* Merges #1847 from @SnailCoil
2020-08-20 17:51:02 -07:00
Aaron Snailwood
6277046213 fix typo in asyncMatcher toBePending comment 2020-08-20 10:07:35 -07:00
Steve Gravrock
6b9739030d Fixed future deprecations 2020-08-02 12:57:28 -07:00
Steve Gravrock
b0d949e0d5 Merge branch 'patch-1' of https://github.com/snowman/jasmine into main
* Merges #1839 from @snowman
    * Fixes script and CSS URLs in standalone example
2020-07-25 09:21:08 -07:00
snowman
dfdcfc5be5 Update README.md
Remove extra "jasmine/" directory in code example
2020-07-25 13:27:00 +08:00
Steve Gravrock
e5bb89847f Use jasmine-browser from npm
The current released version now works with IE, so we no longer need to
depend on main.
2020-07-23 17:29:14 -07:00
Steve Gravrock
1f68ed836e Updated the release docs 2020-07-23 17:26:43 -07:00
Steve Gravrock
c4e65e4a9a wip 2020-07-23 16:50:54 -07:00
Steve Gravrock
0cfeb0b9c3 Fixed link to custom object formatter tutorial 2020-07-23 16:36:56 -07:00
Steve Gravrock
d51da18808 Bump version to 3.6.0 2020-07-23 16:02:30 -07:00
Steve Gravrock
6f3e85f755 Only run long property tests once on CI 2020-07-16 13:03:04 -07:00
Steve Gravrock
d04b813cab Merge https://github.com/buildgroundwork/jasmine
* Merges #1766 from @amilligan
2020-07-16 10:18:08 -07:00
Steve Gravrock
70c416d5c9 Fixed jsdocs for recent additions 2020-07-10 15:41:02 -07:00
Steve Gravrock
226d3ba939 Added IE back to the Travis matrix
Now that jasmine-browser works correctly with IE, we can resume testing
against it.
2020-07-09 11:42:29 -07:00
Steve Gravrock
aa6cc31057 Show diffs involving root-level asymmetric equality testers
* Fixes #1831
2020-07-08 17:02:11 -07:00
Steve Gravrock
f8ae3eaeaa Built distribution 2020-07-08 16:53:53 -07:00
Steve Gravrock
db6aa8f3f8 Use a version of eslint that works on Node 8 2020-07-02 08:49:23 -07:00
Steve Gravrock
4e2f703615 Check for syntax and standard library objects that don't work in IE 2020-07-01 17:34:59 -07:00
Steve Gravrock
ba2aae63be Run eslint against all files 2020-07-01 16:09:14 -07:00
Steve Gravrock
fb23277367 Removed IE from Travis build matrix
We still support IE 10 and 11, but the Node selenium-webdriver has
serious problems with it. Until that's fixed or worked around, IE builds
won't pass. This gets us otherwise green so we can easily see if
anything else is broken.
2020-07-01 12:30:24 -07:00
Steve Gravrock
8cd4873e48 Removed broken Sauce status image 2020-06-29 14:37:08 -07:00
Steve Gravrock
11b63e4e3e Fixed references to master in docs 2020-06-29 14:36:00 -07:00
Steve Gravrock
b3ab9fad9d Updated toHaveBeenCalledOnceWith for new matcher interface 2020-06-26 15:14:02 -07:00
Steve Gravrock
13b967b59c Merge branch 'feat/to-have-been-called-once-with' of https://github.com/Maximaximum/jasmine into pr-merge
* Merges #1801 from @Maximaximum
* Fixes #1717
2020-06-26 15:05:04 -07:00
Steve Gravrock
0253d4fb71 Merge branch 'update-throwError-to-throw-objects' of https://github.com/terencehonles/jasmine
* Merges #1822 from @terencehonles
2020-06-26 15:00:32 -07:00
Steve Gravrock
44875673c1 Merge branch '1821-tests' of https://github.com/dasch-swiss/jasmine
* Merges #1829 from @tobiasschweizer
* Fixes #1821
2020-06-26 14:56:08 -07:00
Terence D. Honles
3943cc2ddb allow spy throwError to throw an Object
When using the following code to simulate a node error:

  spyOn(process, 'kill').and.throwError({code: 'ESRCH'})

The object passed in will be converted to a string by the Error
constructor and result in '[object Object]' which is not very useful.
This PR changes the ``throwError`` spy strategy to only convert
strings into an Error object, but any other objects which are passed
in will be thrown as is. This means the spy strategy can never emulate
throwing a bare string ``throw 'error'``, but this would be a backward
incompatible change.
2020-06-25 18:12:00 -07:00
Steve Gravrock
f4753ac0a4 Fixed syntax errors in IE 10 2020-06-25 07:36:06 -07:00
Tobias Schweizer
ce2161ca32 Add additional test for equals matcher 2020-06-25 09:41:39 +02:00
Steve Gravrock
17eda7a2de Depend on head of jasmine-browser
This should fix CI, and can be reverted once a new version of
jasmine-browser that contains 33bd0fcb0ba990102dcd846e673d07b11041dd44
has been published.
2020-06-24 17:50:16 -07:00
Steve Gravrock
7119720fc7 Merge branch 'dp/missing-punctation' of https://github.com/dirkpuge/jasmine
* Merges #1828 from @dirkpuge
2020-06-23 17:02:47 -07:00
Steve Gravrock
f4e192a428 Merge branch 'expose-property' of https://github.com/johnjbarton/jasmine
* Merges #1820 from @johnjbarton
2020-06-23 16:58:54 -07:00
Dirk Puge
45ad7fd13c Added missing periods 2020-06-21 11:48:05 -04:00
johnjbarton
0cb304131f fix(env): expose setSpec/SuiteProperty on interface 2020-05-26 14:50:01 -07:00
Steve Gravrock
8a731e17a7 Improved jsdocs for user-specified spec/suite properties 2020-05-05 17:58:16 -07:00
Steve Gravrock
7416c176a7 Merge branch 'properties' of https://github.com/johnjbarton/jasmine
* Merges #1763 from @johnjbarton
2020-05-05 17:45:43 -07:00
Maksym Kobieliev
0f6ebaa784 Merge branch 'master' into feat/to-have-been-called-once-with 2020-04-14 22:08:13 +03:00
Maksym Kobieliev
f14f620e15 Merge pull request #1 from jasmine/master
Merge master
2020-04-14 22:07:34 +03:00
Maksym Kobieliev
e94e6c5b75 Fix failing unit test 2020-04-14 22:01:56 +03:00
johnjbarton
f90d9943fe feat(env): setSpecProperty/setSuiteProperty(key, value) to attach data to tests
Use setSpecProperty to attach key/value pairs to spec results that can be
picked up in specialized jasmine reporters.  Example use-cases
include:
  * Tagging specs with URLs or string-tokens referencing test-plan docs.
  * Recording performance information for blocks of JS.
Similarly setSuiteProperty attaches key/value pairs to suite results
2020-04-14 11:27:14 -07:00
Steve Gravrock
8991b1bba3 Fixed toHaveSize matcher on IE 10 & 11 2020-04-12 21:22:14 -07:00
Steve Gravrock
78c3a007ad Fixed test failure in Firefox 74 2020-04-11 12:08:49 -07:00
Steve Gravrock
30b31096b8 Merge branch 'master' of https://github.com/chivesrs/jasmine
* Merges #1802 from @chivesrs
2020-04-11 11:32:08 -07:00
Steve Gravrock
2b318a6154 Merge branch 'master' of https://github.com/parloti/jasmine
* Merges #1807 from @parloti
* Fixes #1775
* Prevents undesired reloads when karma-jasmine-html-reporter is used
2020-04-11 11:30:25 -07:00
Steve Gravrock
41293714fd Merge branch 'tobepending' of https://github.com/DCtheTall/jasmine
* Merges #1808 from @DCtheTall
* Fixes #1803
2020-04-11 11:17:49 -07:00
DCtheTall
08779f2657 add missing trailing newline 2020-04-09 15:20:23 -04:00
DCtheTall
76a99aef86 add missing trailing newline 2020-04-09 15:19:47 -04:00
DCtheTall
6b213a958d Add expectAsync().toBePending() 2020-04-09 15:13:33 -04:00
Alex Parloti
9a7dfb15d2 fix #26
fix #26
Returning false will cause 'zone.js' to invoke e.preventDefault(), preventing the page from reloading.
2020-04-02 21:01:56 +02:00
Maksym Kobieliev
ec9904bf52 Fix test 2020-04-02 21:38:54 +03:00
Maksym Kobieliev
bcc28d7063 Output a diff if there was only one call, but with wrong parameters 2020-04-02 21:31:17 +03:00
Gregg Van Hove
79d55216fc Use internal type checks instead of instanceof to support browsers that don't include the types 2020-03-18 08:57:44 -07:00
Gregg Van Hove
7e940542f8 Merge branch 'wokier-toHaveSize'
- Merges #1796 from @wokier
2020-03-18 08:13:50 -07:00
Gregg Van Hove
ec3ebcb7bb Clean up toHaveSize 2020-03-18 08:13:21 -07:00
Francois Wauquier
c521b4d47c toHaveSize 2020-03-18 08:13:10 -07:00
Chives
66fe69a149 Add test for resolveTo/rejectWith with empty parameters 2020-03-16 03:15:58 -04:00
Maksym Kobieliev
e13fd13529 Add a toHaveBeenCalledOnceWith matcher 2020-03-13 20:41:24 +02:00
Gregg Van Hove
f1eac6fb04 Merge branch 'chivesrs-master'
- Merges #1797 from @chivesrs
2020-03-12 12:28:08 -07:00
Chives
6440ca434d Add trailing newlines to example code 2020-02-29 04:30:03 -05:00
Steve Gravrock
93ad31e0af Correctly report spec and suite duration
Previously, suite duration was always reported as 0 and spec duration
was always reported as null. Suites always used a no-op timer, and
specs set their result.duration after the result had already been sent
to reporters.

Fixes #1676.
2020-02-22 16:53:36 -08:00
Steve Gravrock
a6a9550d1e Fixed 'since' versions for MatchersUtil 2020-02-13 10:52:54 -08:00
Steve Gravrock
6c68715554 Removed unnecessary uses of new 2020-02-13 09:26:33 -08:00
Steve Gravrock
258d55469e Merge branch 'cof-merge-candidate'
* Simplifies the matcher interface
* Adds support for custom object formatters
2020-02-12 15:16:28 -08:00
Steve Gravrock
5096d9af4e Don't construct unnecessarily asymmetricEqualityTesterArgCompatShims
This speeds up MatchersUtil#equals by about 6-7x.
2020-02-12 14:23:03 -08:00
Steve Gravrock
3be797c8d8 Fixed diffs involving jasmine.objectContaining 2020-02-12 14:22:51 -08:00
Gregg Van Hove
d10e8c2ddf Merge branch 'enelson/callThrough-constructor' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/callThrough-constructor
- Merges #1782 from @enelson
- Fixes #1760
2020-02-12 11:39:29 -08:00
Steve Gravrock
c2ada1af95 Merge branch 'custom-object-formatters' into cof-merge-candidate 2020-02-11 13:51:17 -08:00
Pivotal
ea3dd9dffc Refer to MatchersUtil instances as matchersUtil, not util 2020-02-10 17:26:05 -08:00
Steve Gravrock
d41139fea2 Added jsdocs for MatchersUtil 2020-02-10 17:26:05 -08:00
Steve Gravrock
873d1c2945 Use custom object formatters for any part of a diff, not just leaf nodes 2020-02-10 17:26:00 -08:00
Steve Gravrock
25816a6e77 Added support for custom object formatters
Custom object formatters allow users to customize how an object is
stringified in matcher failure messages. This can already be done by
adding a `jasmineToString` method to the objects in question. But
it's not always desirable or possible to do that, particularly when
objects of a given "type" do not inherit from a specific prototype.
For instance, suppose a web service returns a list of foos that are
deserialized from JSON, e.g.:

   { fooId: 42, /* more properties */ }

The only way to define `jasmineToString` on those is by writing code to
add it to each instance at runtime. But a custom object formatter can
recognize that the object it's looking at is a foo and format it
accordingly:

   jasmine.addCustomObjectFormatter(function(obj) {
      if (typeof obj.fooId !== 'number') {
            return undefined;
        }

        return '[Foo with ID ' + obj.fooId + ']';
    });

Unlike `jasmineToString`, custom object formatters are scoped to a
particular spec or suite and don't require any changes to the code
under test.
2020-02-10 17:26:00 -08:00
Steve Gravrock
1f23f1e4d2 Inject a per-runable pretty printer into MatchersUtil
This will allow us to add support for custom object formatters, which
will be a per-runable resource like custom matchers, by injecting them
into the pretty-printer.
2020-02-10 17:26:00 -08:00
Steve Gravrock
dec67bd535 Don't require matchers and asymmetric equality testers to pass custom object formatters back to Jasmine
This makes it easier to write high quality matchers and asymmetric equality
testers, and is also a step toward supporting custom object formatters.

Previously, Jasmine passed custom object formatters as the second argument
to matcher factories and as and the second argument to asymmetric equality
testers' `asymmetricMatch` method. Matchers and asymmetric equality testers
were responsible for passing the custom object formatters to methods like
`matchersUtil#equals`:

  function toEqual(util, customEqualityTesters) {
    return {
      compare: function(actual, expected) {
        // ...
        result.pass = util.equals(actual, expected, customEqualityTesters, diffBuilder);

And:

  ArrayContaining.prototype.asymmetricMatch = function(other, customTesters) {
    // ...
    for (var i = 0; i < this.sample.length; i++) {
      var item = this.sample[i];
      if (!j$.matchersUtil.contains(other, item, customTesters)) {
        return false;
      }
    }

With this change, that is no longer necessary. Matchers and asymmetric
equality testers can ignore the existence of custom equality testers and
still fully support them:

  function toEqual(util) {
    return {
      compare: function(actual, expected) {
        // ...
        result.pass = util.equals(actual, expected, diffBuilder);

And:

  ArrayContaining.prototype.asymmetricMatch = function(other, matchersUtil) {
    // ...
    for (var i = 0; i < this.sample.length; i++) {
      var item = this.sample[i];
      if (!matchersUtil.contains(other, item)) {
        return false;
      }
    }

The old interfaces are still supported, for now, but will be deprecated
in a future commit and removed in the next major release after that.

In addition to making matchers and custom equality testers simpler,
this change sets the stage for adding support for custom object
formatters. Those will be architecturally similar to custom equality
testers, and by injecting a `MatchersUtil` instance everywhere we can
add them without requiring user code to pass them around as used to be
the case with custom object formatters.
2020-02-10 17:25:50 -08:00
Steve Gravrock
83b336d9d1 Merge branch 'matcher-integration-tests' 2020-02-06 18:16:06 -08:00
Elliot Nelson
be3c8275d4 Tidy up SpyStrategy#exec 2020-02-06 10:34:55 -05:00
Elliot Nelson
bf4694333c Improve wrapper function and parameter naming 2020-02-06 10:29:02 -05:00
Elliot Nelson
9febe3159d Allow callThrough to call constructor functions without errors 2020-01-28 19:40:44 -05:00
Steve Gravrock
5e98ee951c Realign the browser testing matrix to match current reality
* Use Windows instead of Linux so we can get current browsers from Sauce.
* Test against the version of Firefox that corresponds to ESR as well as
  latest.
* Test the latest Edge rather than a specific older version.
* Test Safari 8 and 13 instead of 8, 9 and 10. What works in those versions
  is likely to work in the ones in between.
2020-01-20 12:08:01 -08:00
Steve Gravrock
fd5b9ce1ae Fixed spec failure in IE 2020-01-20 11:40:26 -08:00
Steve Gravrock
58c63e98bb Include stack traces in unhandled promise rejection messages 2020-01-20 10:50:42 -08:00
Steve Gravrock
7f392d188e Don't leak global error handlers between Jasmine's own tests 2020-01-20 10:18:29 -08:00
Steve Gravrock
6baf3a9270 Merge branch 'unhandledrejection' of https://github.com/johnjbarton/jasmine into browser-unhandled-rejections
* Merges #1778 from @johnjbarton
* Fixes #1777
2020-01-15 22:10:50 -08:00
johnjbarton
1545112744 feat(GlobalErrors): Route unhandledrejections to onerror
Fixes #1777
2020-01-14 09:38:59 -08:00
Steve Gravrock
8a5216401f Built distribution 2020-01-11 14:29:24 -08:00
Steve Gravrock
fffb8abb24 Moved property tests to the main suite
Property tests can only run in Node, so they were previously in another
directory that only gets run in Node. Now they're next to the related
non-property tests and marked pending in the browser. This makes it more
likely that a developer who normally only runs tests in the browser will
notice and run them.
2020-01-11 10:49:37 -08:00
Steve Gravrock
17e9088ac5 Merge branch 'add-it-naming' of https://github.com/johnlinp/jasmine
* Merges #1772 from @johnlinp
2020-01-11 09:17:45 -08:00
Steve Gravrock
d19ffcc231 Merge branch 'consider-all-error-messages' of https://github.com/vhermannitk/jasmine
* Merges #1776 from @vhermannitk
* Fixes #1771
2020-01-11 09:14:20 -08:00
Valentin Hermann
0b4a9edff8 Added some tests and modified the source code instead of the build product 2020-01-08 10:55:14 +01:00
Valentin Hermann
e02c24d151 Revert "Improves method messagePrefixLength. Now error messages like ReferenceError or TypeError are considered, too"
This reverts commit 913ad50a76.
2020-01-08 08:47:08 +01:00
Valentin Hermann
913ad50a76 Improves method messagePrefixLength. Now error messages like ReferenceError or TypeError are considered, too 2020-01-07 15:49:43 +01:00
Valentin Hermann
c395c525dc Revert "Improves method messagePrefixLength. Now error messages like ReferenceError or TypeError are considered as well"
This reverts commit 12fefa4b3d.
2020-01-07 15:41:02 +01:00
Valentin Hermann
12fefa4b3d Improves method messagePrefixLength. Now error messages like ReferenceError or TypeError are considered as well 2020-01-07 15:23:37 +01:00
Steve Gravrock
88b98277bc Fixed Travis build 2020-01-04 16:15:18 -08:00
Steve Gravrock
4eded6ab61 Added basic property tests for matchersUtil.equals
* See #1764 from @dubzzz
* Property tests are only run in Node, not browser.
* The Travis build sets JASMINE_LONG_PROPERTY_TESTS to enable much more
  thorough (but slow) testing.
2020-01-04 14:52:34 -08:00
John Lin
6c766b7785 Describe the naming for the function it()
When I first saw it(), I was wondering if the name "it" is
an abbreviation of anything. After some search, I finally
realized that the name is only a pronoun. Therefore, I
think it's worthwhile to include it in the documentation.
2019-12-16 12:50:18 +08:00
Adam Milligan
13ff1e037e Make changes in source files 2019-11-22 17:47:20 -05:00
Steve Gravrock
a00f995c68 Added integration tests for existing matcher interfaces 2019-11-17 15:11:58 -08:00
Steve Gravrock
795a80ec66 Added integration tests for asymmetric equality testers 2019-11-17 15:11:53 -08:00
Adam Milligan
3d1a96e020 Extend Jasmine env into correct global 2019-11-05 10:54:46 -05:00
Adam Milligan
076093c16c Properly import jasmineRequire object before using 2019-11-04 11:38:53 -05:00
Steve Gravrock
8d53f4d202 Fixed objectContaining to not match when the expected is the empty object and the actual is a non-object 2019-11-02 14:38:06 -07:00
Steve Gravrock
71631a6529 Test IE before other browsers on Travis
If the tests only fail on one browser, it's usually IE. So testing
IE first gives us faster feedback in cases where we're actively
watching the Travis build.
2019-11-02 13:14:49 -07:00
Steve Gravrock
bed56a76f8 Merge branch 'fix/number-compare-failure' of https://github.com/dubzzz/jasmine
* Merges #1764 from @dubzzz
2019-11-02 11:52:01 -07:00
Nicolas DUBIEN
97fe2e7c95 Fix: Jasmine reports toEqual(0, Number.MIN_VALUE) to be true 2019-10-31 00:31:27 +01:00
Steve Gravrock
ef3f127d27 Fixed comparison between ObjectContaining and non-objects on IE 2019-09-28 18:39:43 -07:00
Steve Gravrock
472f61ab37 Provide better diffs for object graphs that include objectContaining
Turns this output:
    Expected $[0].foo = Object({ a: 4, b: 5 }) to equal <jasmine.objectContaining(Object({ a: 1, c: 3 }))>.

into this:
    Expected $[0].foo.a = 4 to equal 1.
    Expected $[0].foo.c = undefined to equal 3.

And turns this output:
    Expected spy jasmineDone to have been called with:
       [ ... snipped very long expected call ]
    but actual calls were:
       [ ... snipped very long actual call ]

    Call 0:
      Expected $[0] = Object({ overallStatus: 'failed', totalTime: 1, incompleteReason: undefined, order: Order({ random: true, seed: '88732', sort: Function }), failedExpectations: [ Object({ matcherName: 'toBeResolved', passed: false, message: 'Suite "a suite" ran a "toBeResolved" expectation after it finished.
      Did you forget to return or await the result of expectAsync?', error: undefined, errorForStack: Error, actual: [object Promise], expected: [  ], globalErrorType: 'lateExpeztation' }) ], deprecationWarnings: [  ] }) to equal <jasmine.objectContaining(Object({ failedExpectations: [ <jasmine.objectContaining(Object({ passed: false, globalErrorType: 'lateExpectation', message: 'Suite "a suite" ran a "toBeResolved" expectation after it finished.
      Did you forget to return or await the result of expectAsync?', matcherName: 'toBeResolved' }))> ] }))>.

into this:
    Expected spy jasmineDone to have been called with:
       [ ... snipped very long expected call ]
    but actual calls were:
       [ ... snipped very long actual call ]

    Call 0:
      Expected $[0].failedExpectations[0].globalErrorType = 'lateExpeztation' to equal 'lateExpectation'.
2019-09-28 18:03:12 -07:00
Steve Gravrock
10dbf8be98 Indent multiline failure messages in the output of withContext
This makes it easier to see where each failure message begins and ends.

Before:
   Some context: a
   multiline
   message

After:
   Some context:
       a
       multiline
       message
2019-09-28 12:38:28 -07:00
Steve Gravrock
a497d0942a Report async expectations that complete after the runable completes
It's very easy to forget to `await` or `return` the promise returned
from `expectAsync`. When that happens, the expectation failure will
occur after the spec or suite's result has been reported to reporters,
and the failure will typically not be shown to the user. This change
adds a top-level suite failure in that case, similar to the way we
report unhandled exceptions or promise rejections that occur after the
runable completes. Adding the error at the top level gives us the best
chance of getting in before the set of failures we add it to is sent
to reporters.

See #1752.
2019-09-27 18:31:01 -07:00
Gregg Van Hove
9a41154e3b Merge branch 'apla-master'
- Merges #1678 from @apla
2019-09-23 16:48:22 -07:00
ivan baktsheev
fc3eb0fbd8 Handle node.js assert as an error in your specs 2019-09-23 16:47:07 -07:00
Steve Gravrock
223924a7a1 Fixed matchersUtil.contains test to fail correctly 2019-09-22 08:44:15 -07:00
Gregg Van Hove
99799f72b3 Still need some ruby stuff around to release the jasmine-core gem 2019-09-20 17:15:47 -07:00
Gregg Van Hove
e8263e38aa bump version to 3.5.0 2019-09-20 16:57:20 -07:00
Steve Gravrock
53561ae71f Show details of syntax (etc) errors when loading Jasmine's own specs 2019-09-11 13:31:01 -07:00
Steve Gravrock
68f25a758d Don't create env instances in beforeEach 2019-09-11 13:31:01 -07:00
Steve Gravrock
96ba66ad60 Built distribution 2019-09-10 11:23:27 -07:00
Steve Gravrock
ba4a8d1d00 Fixed jsdocs 2019-09-10 11:23:11 -07:00
Steve Gravrock
65d9e93a88 Removed broken & long-disabled JsApiReporter integration specs 2019-09-10 09:38:38 -07:00
Steve Gravrock
2d3ac38df8 toBeRejectedWithError can expect the error to be Error, not just a subtype 2019-09-06 14:17:52 -07:00
Steve Gravrock
5a219da848 Added basic integration tests for all built-in matchers 2019-09-06 14:10:16 -07:00
Steve Gravrock
f056f3b86c Fixed indentation 2019-09-06 13:43:30 -07:00
Steve Gravrock
aeb0b73008 Merge branch 'dtychshenko-1740-fail-on-no-expectations'
* Merges #1743 from @dtychshenko
* Fixes #1740
2019-09-05 09:50:12 -07:00
Dmitriy T
7263a38c3f Adds new configuration option to failSpecWithNoExpectations that will report specs without expectations as failures if enabled 2019-09-05 09:47:38 -07:00
Gregg Van Hove
e8870db8d3 Merge branch 'fix-missing-asynchronous-stacktrace' of https://github.com/prantlf/jasmine into prantlf-fix-missing-asynchronous-stacktrace
- Merges #1738 from @prantlf
- Fixes #1728
2019-09-04 17:42:07 -07:00
Steve Gravrock
35d15085e3 Show argument diffs in toHaveBeenCalledWith failure messages
* Fixes #1641
2019-09-03 17:18:07 -07:00
Steve Gravrock
19292e4ea4 Stop testing against PhantomJS
PhantomJS is at end of life, and the last version of Selenium that supported
it was 3.6.0, released almost three years ago. We can't test Jasmine against
PhantomJS without pinning key pieces of the project to increasingly outdated
versions of key libraries.
2019-09-03 15:40:53 -07:00
Steve Gravrock
ba71989d4b Fixed code formatting 2019-09-03 15:39:00 -07:00
Steve Gravrock
f8e5ea14bc Fail the CI build if the promise returned from jasmineBrowser.runSpecs is rejected 2019-09-03 15:34:56 -07:00
Steve Gravrock
92dfbdcdc9 Depend on acorn to work around broken deduping
See <https://github.com/eslint/espree/issues/393>.
2019-09-03 15:30:42 -07:00
Steve Gravrock
8ad1dd163b Merge branch 'arrayContaining-actuals-must-be-arrays' of https://github.com/divido/jasmine
* Merges #1746 from @divido
* Fixes #1745
2019-08-30 13:12:47 -07:00
Steve Gravrock
ded8b760aa Merge branch 'UziTech-patch-1'
* Merges #1732 from @UziTech
2019-08-30 10:27:53 -07:00
Tony Brix
07318fba37 docs change 2019-08-30 12:14:19 -05:00
Steve Gravrock
c42358c686 Fixed test failure on IE 2019-08-30 09:30:23 -07:00
Tony Brix
f77ee32c56 Add custom async matchers 2019-08-30 09:30:14 -07:00
David Diederich
0bd636b5d2 Updated arrayContaining to require actual values to be arrays
If the actual value of a test was a string, this was matching against arrays
that contained the strings. This was due to the use of the contains matcher,
which against string looks for substrings, when it was intended to look for
array elements.
2019-08-30 01:09:53 -04:00
Pivotal
008b80adc5 Merge branch 'enelson/default' of https://github.com/elliot-nelson/jasmine
* Merges #1716 from @elliot-nelson
2019-08-29 13:50:27 -07:00
Steve Gravrock
1a63ab4677 Accept configurations with Promise: undefined.
Fixes Karma and anything else that uses Env#configuration
as a starting point for a Jasmine config.
2019-08-26 15:45:13 -07:00
Ferdinand Prantl
3a7fc63879 Pick the error instance to pass to error handlers in QueueRunner
The first number is the error message in HTML5 browser, which does not include
the call stack. The error instance allows logging the complete call stack in
reporters.
2019-08-11 09:32:31 +02:00
Ferdinand Prantl
527619b0aa Restore the original global error hanler to pass all parameters along 2019-08-11 09:31:43 +02:00
Gregg Van Hove
0449b35f5a Merge branch 'tobe-tostring' of https://github.com/johnjbarton/jasmine into johnjbarton-tobe-tostring
- Merges #1718 from @johnjbarton
- Fixes #1726
2019-08-07 12:03:46 -07:00
Steve Gravrock
e50a7b6985 Merge branch 'add-map-set-matchers' of https://github.com/eventlistener/jasmine
* Merges #1741 from @eventlistener
2019-08-03 12:18:35 -07:00
Steve Gravrock
b2d9aab2b8 Use the same spec file pattern for both node and browser 2019-08-03 12:17:52 -07:00
Olga Kozlova
b01d86840a mapContaining and setContaining asymmetric matchers 2019-08-03 22:14:48 +03:00
sgravrock
385ad33f60 Merge pull request #1736 from olleolleolle/patch-1
Gemspec: Drop EOL'd property rubyforge_project
2019-08-03 08:58:01 -07:00
Steve Gravrock
18195a868c Updated async timeout message
There are now multiple ways to do async functions, and callbacks
are probably the least common in new code, so the message should
be more general rather than referring to callbacks.
2019-08-03 08:25:57 -07:00
Ferdinand Prantl
7c3434723e Use the documented interface to pick the error instance from the global error handler 2019-07-21 23:46:14 +02:00
Ferdinand Prantl
4858a62fdc Add a unit test for the global error handling including stacktrace 2019-07-16 12:00:09 +02:00
Ferdinand Prantl
df4b6e58e2 Pass the error including stacktrace to error handlers and reporters
The global window error handler is used to handle errors thrown from within asynchronous functions and tests. The first parameter is the error; the fifth parameter is the full error object including the stacktrace. Searching for the first occurrence of an error instance to work with browsers, which may not comply with the HTML5 standard.
2019-07-15 14:43:22 +02:00
Olle Jonsson
d68b47b76d Gemspec: Drop EOL'd property rubyforge_project 2019-07-14 10:38:36 +02:00
Steve Gravrock
c100bb6242 Made output of toHaveBeenCalledWith more readable
This breaks each call out onto its own line, so that it's much easier to
see where each call starts and how they differ. E.g. previously the output
would be:

    Expected spy foo to have been called with [ 'bar', 'baz', 'qux' ] but actual calls were [ [ 42, 'wibble' ], [ 'bar' 'qux' ], [ 'grault '] ]

Now it's:

    Expected spy foo to have been called with:
      [ 'bar', 'baz', 'qux' ]
    but actual calls were:
      [ 42, 'wibble' ],
      [ 'bar' 'qux' ],
      [ 'grault '].
2019-07-13 10:37:05 -07:00
Gregg Van Hove
c37e9b9db0 Add saucelabs badge to readme 2019-07-07 19:37:09 -07:00
Gregg Van Hove
5e87e1410d update to newer jasmine-browser-runner 2019-07-07 19:20:45 -07:00
Gregg Van Hove
0cd5d9339b Use node 10 for browser based builds 2019-07-07 19:01:36 -07:00
johnjbarton
6324fda065 PrettyPrinter survives if objects throw in toString 2019-06-27 10:35:59 -07:00
Gregg Van Hove
066162d6bc Merge branch 'enelson/spyobjproperty' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/spyobjproperty
- Merges #1722 from @elliot-nelson
- Closes #1569
- Fixes #1442
2019-06-25 16:26:43 -07:00
Gregg Van Hove
ab01fa1978 Merge pull request #1721 from elliot-nelson/enelson/gitattributes
Fix: don't attempt to normalize PNGs (gitattributes)
2019-06-24 16:16:37 -07:00
Elliot Nelson
65e6df55ee Linting fixes 2019-06-20 07:34:31 -04:00
Elliot Nelson
45475f6d1e Allow users to pass property names to createSpyObj 2019-06-20 07:33:10 -04:00
Elliot Nelson
a536ca19f2 Don't attempt to normalize PNGs 2019-06-20 06:46:51 -04:00
Gregg Van Hove
9a6262e3cd bump browser runner to new version 2019-06-14 16:42:10 -07:00
Gregg Van Hove
e7d0d742a8 only turn on sauce_connect for jobs that need it (I think) 2019-06-14 15:43:14 -07:00
Gregg Van Hove
031515db23 rejigger travis again to not run sauce jobs for PRs 2019-06-14 15:27:24 -07:00
Gregg Van Hove
49fd22ffe6 move everything we can into the env matrix for travis 2019-06-14 15:15:29 -07:00
Gregg Van Hove
5c058b5bc4 Don't include node 10 & 12 in matrix, we're explicit later 2019-06-14 15:11:41 -07:00
Gregg Van Hove
18dbbca436 Refactor travis matrix to compress a bit more 2019-06-14 15:10:16 -07:00
Gregg Van Hove
3e888105f0 Calculate total suite run time inside the env and report in jasmineDone 2019-06-14 14:59:33 -07:00
Gregg Van Hove
15f969bee7 Add @since to most JSDoc comments
- See jasmine/jasmine.github.io#117
2019-06-12 16:23:12 -07:00
Gregg Van Hove
984018bfdf Make no expectations in HTML Reporter message a warning
- Fixes #1704
2019-06-12 13:31:25 -07:00
Gregg Van Hove
0f4e53d0e6 Update ci script to pass linting 2019-06-12 12:15:34 -07:00
Gregg Van Hove
c73c5a9dbd WIP 2019-06-12 11:42:47 -07:00
Gregg Van Hove
243adfd4ce Use jasmine-browser-runner to execute browser tests 2019-06-12 11:33:14 -07:00
Elliot Nelson
e07da96354 Apply prettier 2019-06-07 23:33:06 -04:00
Elliot Nelson
96786c793f Allow users to set a default spy strategy 2019-06-07 23:32:13 -04:00
Gregg Van Hove
d610d0bdad Use browser-runner to start server in CI 2019-06-06 14:46:19 -07:00
Gregg Van Hove
0644731680 Switch to using new jasmine-browser-runner to server files for local testing 2019-06-06 14:07:30 -07:00
Gregg Van Hove
8da1fd1ed1 Merge branch 'master' of https://github.com/pixelpax/jasmine into pixelpax-master
- Merges #1713 from @pixelpax
2019-05-30 17:47:16 -07:00
Gregg Van Hove
8af669677a Cleanup spy promise strategies to be more consistent with Jasmine at large
- Rename `resolveWith` to `resolveTo` to match `toBeResolvedTo`
- No longer wrap non-Errors in `rejectWith`

- Fixes #1715
2019-05-23 17:29:12 -07:00
Gregg Van Hove
b4cbe9850f add prettier and eslint 2019-05-21 18:23:48 -07:00
Gregg Van Hove
cf2c5c9acc Merge branch 'enelson/src-cleanup-2' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/src-cleanup-2
- Merges #1708 from @elliot-nelson
2019-05-21 17:45:46 -07:00
Gabriel Elkind
4e10cf84d5 Adds in the source-- whoops! 2019-05-20 23:51:29 -05:00
Gregg Van Hove
9f875ce666 Older versions don't support const, use var 2019-05-20 17:56:27 -07:00
Gregg Van Hove
df6a71e37d Merge branch 'spy-to-string' of https://github.com/johnjbarton/jasmine into johnjbarton-spy-to-string
- Merges #1712 from @johnjbarton
2019-05-20 17:22:05 -07:00
Gregg Van Hove
32a3288c9d Merge branch 'elliot-nelson-enelson/pp' 2019-05-20 17:18:29 -07:00
Gregg Van Hove
b12981a3e7 build dist for rounding fix 2019-05-20 17:17:55 -07:00
Gregg Van Hove
cbbdd360f8 Merge branch 'enelson/pp' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/pp
- Merges #1711 from @elliot-nelson
- Closes #1700
- Closes #1575
2019-05-20 17:13:41 -07:00
Gregg Van Hove
3a89cc92fb Merge branch 'paulvanbrenk-fix-1695'
- Merges #1710 from @paulvanbrenk
- Fixes #1695
2019-05-20 17:10:39 -07:00
Gabriel Elkind
88c8c905ba Adds width to root level html-reporter class 2019-05-20 15:25:38 -05:00
johnjbarton
d1adbdc72b fix(PrettyPrint): jasmine.createSpyObj('obj', ['toString']);
The PrettyPrint handler for scalars uses toString() but if that method
has been spyed on, then the stringify fails with
TypeError: Cannot read property 'length' of undefined.

By hanlding this case earlier in format() we avoid the error.

Add unit test covering this case.
2019-05-20 09:33:47 -07:00
Elliot Nelson
8225bb935f Explicitly test pretty printing objects with nested invalid toString 2019-05-20 09:09:07 -04:00
Elliot Nelson
9f704b6f3a PrettyPrinter handles objects with invalid toString implementations 2019-05-20 09:01:10 -04:00
Paul van Brenk
69a7449e50 Fix toBeCloseTo matcher for Node.js 12 and Chrome 74 2019-05-19 12:46:32 -04:00
Elliot Nelson
b1da6e3960 Cleanup: unused vars, dangling commas, negation 2019-05-18 08:11:47 -04:00
Elliot Nelson
1e855aa9b8 Cleanup: whitespace 2019-05-18 08:10:11 -04:00
Gregg Van Hove
e04d3d8a62 Fix bad merge for spyOnProperty error message 2019-05-17 17:07:47 -07:00
Gregg Van Hove
06814769c6 Merge branch 'enelson/spyregerrors' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/spyregerrors
- Merges #1706 from @elliot-nelson
2019-05-17 16:44:26 -07:00
Gregg Van Hove
309e6df8fd Use Object.create to make an object with null prototype 2019-05-17 16:31:15 -07:00
Gregg Van Hove
ea1bac5b74 Merge branch 'enelson/spyonproperty' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/spyonproperty
- Merges #1705 from @elliot-nelson
2019-05-17 16:21:17 -07:00
Elliot Nelson
befb8995e6 spyOnProperty jasmine-style error messages with usage note 2019-05-17 12:02:44 -04:00
Elliot Nelson
1e13039478 spyOnProperty respects the allowRespy flag 2019-05-17 11:43:22 -04:00
Gregg Van Hove
11b0d95a7d Merge branch 'enelson/toBeInstanceOf' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/toBeInstanceOf
- Merges #1697 from @elliot-nelson
2019-05-16 17:35:09 -07:00
Gregg Van Hove
95f6ba5fa2 Merge branch 'elliot-nelson-enelson/ci-errors' 2019-05-15 17:54:50 -07:00
Gregg Van Hove
d331e9cc38 Merge branch 'enelson/ci-errors' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/ci-errors
- Merges #1701 from @elliot-nelson
2019-05-15 17:54:24 -07:00
Gregg Van Hove
0129a7d007 Update contributing doc based on some of the newer tooling
- Fixes #1702
2019-05-15 17:34:57 -07:00
Elliot Nelson
0fded24d35 Introduce matchers#toBeInstanceOf 2019-05-15 11:51:46 -04:00
Elliot Nelson
c88c772ffb Print global errors encountered during CI runs 2019-05-15 11:39:45 -04:00
Gregg Van Hove
3dde56bbd8 Merge branch 'enelson/spyonall' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/spyonall
- Merges #1699 from @elliot-nelson
- Fixes #1677
2019-05-14 18:01:27 -07:00
Gregg Van Hove
e377f1caae Merge branch 'elliot-nelson-enelson/ci'
- Merges #1598 from @elliot-nelson
2019-05-14 17:21:28 -07:00
Elliot Nelson
91fe87ca56 Simplify error checks in ci.js 2019-05-14 06:57:46 -04:00
Elliot Nelson
ee15309a8f Extend spyOnAllFunctions to include prototype and parent methods 2019-05-11 18:20:13 -04:00
Elliot Nelson
49c03d4a22 Improve error handling in CI test launcher 2019-05-10 06:18:35 -04:00
Gregg Van Hove
9a18fdca27 Merge branch 'enelson/spystrategies' of https://github.com/elliot-nelson/jasmine into elliot-nelson-enelson/spystrategies
- Merges #1688 from @enelson
- See #1590
2019-05-09 17:30:45 -07:00
Elliot Nelson
b2fb92eedd Promise-based strategies are now named resolveWith and rejectWith 2019-05-09 06:12:06 -04:00
Elliot Nelson
df818f3fbc rejectValue wraps non-Errors like throwError does 2019-05-08 09:36:12 -04:00
Elliot Nelson
4731b4ee4d Keep all Promise implementation details internal 2019-05-08 09:13:41 -04:00
Gregg Van Hove
eb30e8179a Update deprecation messages to indicate _future_ removal
- Fixes #1628
2019-05-07 17:10:04 -07:00
Elliot Nelson
95e1890e64 Improved resolveValue/rejectValue error messages 2019-05-07 16:30:48 -04:00
Elliot Nelson
72aa0bbe4d Add resolveValue and rejectValue spy strategies 2019-05-05 08:08:34 -04:00
Steve Gravrock
17a9a6417a Fixed test failure in Firefox 66.0.2 2019-05-04 10:51:34 -07:00
Gregg Van Hove
d856b0548a Merge branch 'megahertz-feature-to-be-rejected-with-error'
- Merges #1686 from @megahertz
- Fixes #1625
2019-05-03 16:36:37 -07:00
Alexey Prokhorov
8ab46566ac Fix failure messages for toBeRejectedWithError matcher 2019-05-03 09:37:11 +04:00
Daniel Kurka
2745d7d515 Add support for ArrayBuffers to matcherUtil.equals.
Fixes #1687
2019-05-02 09:49:21 -07:00
Alexey Prokhorov
35968e4a60 Add toBeRejectedWithError matcher 2019-04-26 01:46:56 +04:00
Gregg Van Hove
afb24d1050 Ignore internal ci.js from npm package
- See #1684
2019-04-22 18:10:43 -07:00
Gregg Van Hove
c6d637dcb3 Bump some dependencies 2019-04-22 18:03:37 -07:00
Gregg Van Hove
2fbeb201bc Fix failure messages for positive/negative infinity matchers
- Fixes #1674
2019-04-16 17:40:07 -07:00
Gregg Van Hove
fd60b5737c Merge pull request #1680 from acinader/patch-1
nit: fix typo
2019-04-15 17:56:23 -07:00
Gregg Van Hove
b994a17039 Merge branch 'FelixRilling-boolean-matcher'
- Merges #1679 from @FelixRilling
2019-04-15 17:48:49 -07:00
Arthur Cinader
74fa38bdfb nit: fix typo 2019-04-14 10:33:51 -05:00
Felix Rilling
369e810791 added #toBeTrue and #toBeFalse matchers 2019-04-14 10:17:59 +02:00
Gregg Van Hove
8fca3b4c11 Fix links in 3.4 release notes 2019-04-03 17:13:18 -07:00
Gregg Van Hove
e636f5f822 Bump version to 3.4 2019-04-03 17:03:07 -07:00
Gregg Van Hove
74fd0e08e7 No fit in the suite 2019-04-01 21:01:22 -07:00
Gregg Van Hove
618e24b2f8 Handle WebSocket events in IE when detecting Errors
- Fixes #1623
2019-04-01 18:52:27 -07:00
Gregg Van Hove
5c7e25e228 Allow excluded specs in CI without breaking the output 2019-04-01 18:52:01 -07:00
Gregg Van Hove
54af109d40 Merge branch 'wood1986-fix/npm-audit-dependencies-and-fast-glob-only-failed-tests'
- Merges #1672 from @wood1986
2019-03-26 17:12:53 -07:00
wood
873a237e3d Consolidate some dev dependencies and use more maintained versions 2019-03-26 17:12:21 -07:00
Gregg Van Hove
8ca4463e01 Make node execution default and override for browsers 2019-03-25 18:37:50 -07:00
Gregg Van Hove
449eb516cc Fix sauce status codes and try travis built-in node support 2019-03-25 18:33:39 -07:00
Gregg Van Hove
a5df5a6ee9 Use the correct env var from travis for tunnels 2019-03-25 18:12:15 -07:00
Gregg Van Hove
be583232b4 bump dependencies for security fixes 2019-03-25 18:01:13 -07:00
Gregg Van Hove
d389d3c002 Merge branch 'wood1986-features/no-ruby'
- Merges #1658 from @wood1986
- Fixes #883
2019-03-25 17:56:19 -07:00
Gregg Van Hove
994d11d4f3 update node CI script to work with SauceLabs 2019-03-25 17:56:06 -07:00
wood
828d14f48e Use node.js for browser-based CI 2019-03-25 17:55:53 -07:00
Gregg Van Hove
f5663a9076 Merge branch 'johnjbarton-duration'
- Merges #1660 from @johnjbarton
- Fixes #1646
2019-03-14 19:12:39 -07:00
johnjbarton
a8c2399dd8 feat(result.duration): report test duration in ms
Wrap spec start/complete in Timer start/elapsed.
configuration.timeSpecDuration = false will disable feature.

 * Add Suite result.duration, elapsed time in ms

 * Remove timeSpecDuration option.

 * Respond to review, use noopTimer
2019-03-14 09:13:57 -07:00
Gregg Van Hove
7c0f013003 Merge branch 'johnjbarton-noop-timer'
- Merges #1669 from @johnjbarton
2019-03-13 17:34:12 -07:00
johnjbarton
ca2b62b00e refactor(Timer): share htmlReporter noopTimer via Timer.js 2019-03-12 16:26:04 -07:00
Gregg Van Hove
4108deca02 Build distribution for various typo PRs 2019-03-11 17:39:03 -07:00
Gregg Van Hove
def278f90f Merge branch 'typo-suites' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-suites
- Merges #1666 from @FelixRilling
2019-03-11 17:38:29 -07:00
Gregg Van Hove
6bd4a29360 Merge branch 'jsdoc-validation' of https://github.com/FelixRilling/jasmine into FelixRilling-jsdoc-validation
- Merges #1667 from @FelixRilling
2019-03-11 17:37:43 -07:00
Gregg Van Hove
fd037f53a3 Merge branch 'typo-comments' of https://github.com/FelixRilling/jasmine into FelixRilling-typo-comments
- Merges #1665 from @FelixRilling
2019-03-11 17:34:44 -07:00
Gregg Van Hove
348242b712 Merge branch 'FelixRilling-typo-received'
- Merges #1664 from @FelixRilling
- Fixes #1663
2019-03-11 17:32:32 -07:00
Felix Rilling
b74e0abee1 Fixed flipped JSDoc. 2019-03-10 11:17:50 +01:00
Felix Rilling
e33b12b17c Fixed typos in test suite descriptions. 2019-03-10 11:07:40 +01:00
Felix Rilling
dde93ade18 Fixed typos in comments. 2019-03-10 11:04:33 +01:00
Felix Rilling
63f900287c Fixed typo "receieved" to "received", Adapted test. 2019-03-10 10:59:56 +01:00
Gregg Van Hove
239a615770 No longer run Node.js v4 on Travis
- Jasmine should still work in Node.js v4, but the jshint task isn't
  working correctly
2019-02-11 13:38:00 -08:00
Gregg Van Hove
92d5957a59 Attempt to skip jshint for node.js v4 2019-02-11 09:46:36 -08:00
Gregg Van Hove
4991f2a713 Merge branch 'print_global_error_type' of https://github.com/jbunton-atlassian/jasmine into jbunton-atlassian-print_global_error_type
- Merges #1632 from @jbunton-atlassian
2019-02-11 09:02:16 -08:00
Gregg Van Hove
0d6db64eb1 Merge branch 'onerror' of https://github.com/johnjbarton/jasmine into johnjbarton-onerror
- Merges #1644 from @jognjbarton
2019-01-30 17:38:27 -08:00
Gregg Van Hove
489fb79d6e fall back to older jshint for older node 2019-01-09 11:08:32 -08:00
Gregg Van Hove
eba8c775f3 update npm dependencies 2019-01-08 17:47:53 -08:00
johnjbarton
c36a005893 Support Error.stack in globalErrors.
See https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror
2019-01-03 16:14:23 -08:00
Gregg Van Hove
37dfe50d99 Stop treating objects with a nodeType as if they are DOM Nodes
- Fixes #1638
2018-12-17 17:10:53 -08:00
Gregg Van Hove
c67a5b830c Fix 3.0 breaking changes list to include note about Spy identity 2018-12-11 17:56:17 -08:00
James Bunton
d803bd12a6 When catching a global error in Node.js, print the type of error 2018-12-11 08:32:45 +11:00
Gregg Van Hove
a621d05fa7 Merge branch 'Havunen-fix-to-equal-ie'
- Merges #1621 from @Havunen
- Fixes #1618
2018-12-03 17:45:06 -08:00
Sampo Kivistö
473f5cd359 Re-use attr variable 2018-11-04 10:44:54 +02:00
Sampo Kivistö
a81e9626df Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality 2018-11-04 10:31:33 +02:00
Gregg Van Hove
b3ccd4312c Bump version to 3.3.0 2018-10-25 09:47:09 -07:00
Gregg Van Hove
5524207658 Add api docs for .not and .withContext 2018-10-24 16:49:31 -07:00
Gregg Van Hove
1b5e0c0c10 Merge branch 'expect-context'
- Fixes #641
2018-10-24 16:32:28 -07:00
Gregg Van Hove
2d303a6e46 Merge common async/sync expectation stuff 2018-10-24 16:17:30 -07:00
Gregg Van Hove
1e47dcf2cc Pull async matchers out to their own functions
- Makes AsyncExpectation closer to Expectation
2018-10-23 16:02:31 -07:00
Gregg Van Hove
ba1e8f8008 Implement withContext for async expectations too 2018-10-22 16:42:36 -07:00
Gregg Van Hove
a91db0dfc2 more rejected to -> rejected with 2018-10-22 16:08:57 -07:00
Gregg Van Hove
1d130036f4 Merge branch 'master' into expect-context 2018-10-22 14:55:20 -07:00
Gregg Van Hove
e6a60a7bef Merge branch 'codymikol-toBeRejectedWith'
- Merges #1615 from @codymikol
- Closes #1600
- Fixes #1595
2018-10-22 11:20:03 -07:00
Gregg Van Hove
fe042fdf82 Use toBeRejectedWith instead of toBeRejectedTo 2018-10-22 11:18:56 -07:00
Gregg Van Hove
06854fe435 Merge branch 'toBeRejectedWith' of https://github.com/codymikol/jasmine into codymikol-toBeRejectedWith 2018-10-22 11:15:05 -07:00
Gregg Van Hove
7b9fc80b8f Merge branch 'tdurtschi-master'
- Merges #1616 from @tdurtshi
- Fixes #1614
2018-10-22 10:59:03 -07:00
Gregg Van Hove
3c47e71619 Also show tip for .not cases 2018-10-22 10:57:16 -07:00
Teagan Durtschi
7cbedcdda7 Add custom message for toBe() matcher when object equality check fails 2018-10-21 12:46:49 -04:00
Cody Mikol
3aa0115ae4 feat(toBeRejectedTo): implement toBeRejectedTo functionality
add functionality to determine whether a promise has been rejected to a
specific value via expectAsync

Fixes: #1595
2018-10-19 23:23:42 -04:00
Gregg Van Hove
440b6934aa Merge branch 'codymikol-assertAsync-promiseLike-support'
- Merges #1613 from @codymikol
- Fixes #1612
2018-10-19 16:24:30 -07:00
Cody Mikol
591bf1144b bugfix(assertAsync): add promiseLike support for angularJS promises
implement a promiseLike method so libraries using non-browser promise
implementations can still utilize assertAsync functionality.

Fixes: #1612
2018-10-18 21:28:32 -04:00
Gregg Van Hove
3ae61b14ad Merge branch 'm1010j-m1010j-add-status-marks-to-standalone'
- Merges #1610 from @m1010j
- Fixes #1596
2018-10-01 12:25:23 -07:00
Matthias Jenny
705a6508d4 Add status marks to standalone 2018-09-26 21:10:20 -04:00
Gregg Van Hove
306882f636 Merge branch 'nitobuendia-patch-1' 2018-09-25 17:29:10 -07:00
Gregg Van Hove
16fef04629 Merge branch 'patch-1' of https://github.com/nitobuendia/jasmine into nitobuendia-patch-1
- Merges #1601 from @nitobuendia
- Fixes #1594
2018-09-25 17:28:57 -07:00
Gregg Van Hove
d180c2026e Merge branch 'master' of https://github.com/Havunen/jasmine into Havunen-master
- Merges #1599 from @Havunen
2018-09-25 17:14:49 -07:00
Gregg Van Hove
92d0882a32 Introduce a configuration object to Env deprecating old single use functions
[finishes #159158038]
2018-09-25 17:08:41 -07:00
Nito Buendia
04679622b0 Add tests for formatting empty content errors. 2018-09-13 20:02:30 +08:00
Nito Buendia
b4cd1ec1ae Format according to style. 2018-09-13 19:48:53 +08:00
Nito Buendia
963b1cca22 Add tests for new unnamed errors. 2018-09-13 19:48:10 +08:00
Nito Buendia
d4f9b41eda Print error message when available
With the current set up, error message is only printed out when error name is available.
There are situations where the ErrorEvent object does not have a `name` property, but the message is still relevant.

For more details see #1594
2018-09-11 23:25:28 +08:00
Sampo Kivistö
1019b045cd Optimized clearTimeout cpu usage 2018-09-06 21:11:05 +03:00
Gregg Van Hove
6b9ae2db7e Merge pull request #1597 from limonte/patch-1
chore(package.json): http -> https
2018-09-04 12:27:05 -07:00
Limon Monte
33d8d2d3f4 chore(package.json): http -> https 2018-09-01 10:16:30 +03:00
Gregg Van Hove
12f56fdb7d bump version to 3.2.1 2018-08-14 17:19:23 -07:00
Gregg Van Hove
afa18e554c Correctly expost spyOnAllFunctions
- See #1581
2018-08-14 17:11:50 -07:00
Gregg Van Hove
7205d07c67 Merge pull request #1588 from fossabot/master
Add license scan report and status
2018-08-08 19:04:21 -07:00
Gregg Van Hove
83ba2eb4d6 Link to the correct repo in release notes 2018-08-08 17:41:24 -07:00
Gregg Van Hove
87865f00a3 Add issue links to release notes 2018-08-08 17:39:10 -07:00
Gregg Van Hove
112672c4a9 bump version to 3.2.0 2018-08-08 17:33:50 -07:00
fossabot
f05ab79731 Add license scan report and status
Signed-off-by: fossabot <badges@fossa.io>
2018-08-07 17:47:31 -07:00
Gregg Van Hove
3a52c444f8 Merge branch 'aeisenberg-spy-all'
- Merges #1581 from @aeisenberg
- Fixes #1421
2018-07-24 17:55:44 -07:00
Andrew Eisenberg
f62eb3b1a8 Add spyOnAllFunctions function
This function will spy on all writable and configurable functionss of
an object that is passed in. It can be used like this:

    spyOnAllFunctions(obj);

This commit addresses https://github.com/jasmine/jasmine/issues/1421
2018-07-20 07:58:17 -07:00
Gregg Van Hove
110c092c9e Fix regular expressions for different browsers 2018-06-18 17:55:24 -07:00
Gregg Van Hove
8bb0e2d494 Merge branch 'ikonst-set-timeout-error-message'
- Merges #1567 from @ikonst
2018-06-18 17:37:39 -07:00
Ilya Konstantinov
8c1b80daae Improve Jasmine timeout error message 2018-06-18 17:36:43 -07:00
Steve Gravrock
ac07c9ea97 Simplified ExpectationFilterChain#modifyFailureMessage 2018-06-09 12:34:30 -07:00
Steve Gravrock
0842a80c68 Cleanup 2018-06-09 12:26:34 -07:00
Gregg Van Hove
e2895a92dc Fix JSDoc naming for Env functions
- See #1565
2018-06-06 17:13:52 -07:00
Gregg Van Hove
03998c1b20 Add documentation for more public functions on Env
- Fixes #1565
2018-06-05 17:13:58 -07:00
Steve Gravrock
9472df0db4 Added a basic set of async matchers
- Fixes #1447
- Fixes #1547
2018-06-04 21:07:44 -07:00
Steve Gravrock
8a01e1f26c .withContext() works with .not 2018-06-02 22:06:53 -07:00
Steve Gravrock
321f161ce5 Made ExpectationFilterChain immutable 2018-06-02 13:57:29 -07:00
Steve Gravrock
202a677637 ExpectationFilterChain WIP 2018-06-02 13:57:07 -07:00
Gregg Van Hove
8f7327cb4d Properly cascade StopExecutionError's up the tree
- Fixes #1563
2018-05-30 17:32:14 -07:00
Gregg Van Hove
3636014917 Merge branch 'hide-grey-specs' of https://github.com/SamFare/jasmine into SamFare-hide-grey-specs
- Merges #1561 from @SamFare
2018-05-23 17:15:40 -07:00
SamFare
92d33c79c7 Implemented hiding of disabled specs 2018-05-22 13:30:33 +01:00
Steve Gravrock
e2897ce619 Added expect().withContext() to provide additional information in failure messages 2018-05-14 21:18:55 -07:00
Steve Gravrock
282c436463 Implemented matcher negation as a filter 2018-05-13 23:01:55 -07:00
Steve Gravrock
5cc22740c9 Test the public-ish interface 2018-05-13 22:48:58 -07:00
Steve Gravrock
533bda5d24 Split Expectation#wrapCompare into several smaller functions 2018-05-13 22:48:58 -07:00
Steve Gravrock
9fe9569b24 Additional tests for negated matcher failure messages 2018-05-13 22:48:20 -07:00
Steve Gravrock
e2d9eefccd Line-break long expectation failure messages
This makes failures somewhat easier to read. We still preserve whitespace
within lines to make whitespace-only failures readable, e.g.
expect('foo  bar').toEqual('foo bar'). See #296.
2018-05-12 09:42:38 -07:00
Gregg Van Hove
ced2b114e4 Better detection of DOM Nodes for equality
- Also use JSDom if a real one isn't present to get some more coverage
  there

- Fixes #1172
2018-05-04 18:01:08 -07:00
Gregg Van Hove
f7097281c9 IE doesn't support .name on a function 2018-05-03 17:34:15 -07:00
Gregg Van Hove
01a1113387 Merge branch 'yinm-fix-typo'
- Merges #1555 from @yinm
2018-05-03 17:21:18 -07:00
yinm
4d0b47ac4c Fix typo from incimplete to incomplete 2018-05-03 17:46:49 +09:00
Gregg Van Hove
d6cfc4a9b5 Merge branch 'riophae-master'
- Merges #1551 from @riophae
2018-05-02 17:52:03 -07:00
Fangzhou Li
fbcdbf5ab1 Allow omitting the name argument: createSpy(func) 2018-04-29 06:07:22 +08:00
Gregg Van Hove
7e14a97371 Explicitly pass in timing functions in mock clock integration specs
- This way we can make sure that clear stack always works no matter
  how long the suite in the spec is

[fixes #153518103]
2018-04-23 17:25:11 -07:00
Gregg Van Hove
c440d13754 Use the same global for everything in Env
- No longer use `getGlobal` for clearStack and QueueRunner
2018-04-13 17:14:48 -07:00
Gregg Van Hove
8e8f09b41f Force reinstall bundler and include firefox again 2018-04-03 17:33:20 -07:00
Gregg Van Hove
1decb14807 Ensure rubygems is up-to-date on travis
- See travis-ci/travis-ci#8969
2018-04-03 17:13:27 -07:00
Gregg Van Hove
a978f50f1d name new global status stuff correctly in API docs 2018-04-02 17:20:39 -07:00
Steve Gravrock
74287c578c Check for accidental global variable creation 2018-03-25 12:01:50 -07:00
Steve Gravrock
7f1cdc2d02 Fixed global variable leak
- Fixes #1534
2018-03-25 12:00:56 -07:00
Steve Gravrock
847a959b13 Merge branch 'handle-rejection' of https://github.com/johnjbarton/jasmine
- Merges #1521 from @johnjbarton
2018-03-24 19:49:58 -07:00
Steve Gravrock
05015a8b3e Correctly format stack traces for errors with multiline messages
- Fixes #1526
2018-03-10 12:03:08 -08:00
Steve Gravrock
6f960d8662 Merge branch 'better-array-errors' of https://github.com/majidmade/jasmine
- Merges #1527 from @majidmade
- Fixes #1485
2018-03-10 07:42:34 -08:00
Majid Razvi
11b8b59e03 Change message for extra elements at end of actual array. #1485 2018-03-10 00:05:07 -07:00
johnjbarton
f1ebe05f1d Report unhandled rejections as globalErrors.
Extend existing support for uncaughtExceptions to unhandledRejections now that many tests are async.
2018-03-01 16:47:50 -08:00
Gregg Van Hove
85b2a8c6c4 add some links to more tutorials from the api docs 2018-03-01 10:48:18 -08:00
Gregg Van Hove
557fb4ed72 proper links in release notes 2018-02-27 12:01:28 -08:00
Gregg Van Hove
ee52023b3d Bump version to 3.1 2018-02-27 11:57:20 -08:00
Gregg Van Hove
91296a44f2 Remove Safari 7 from Travis matrix 2018-02-27 11:10:07 -08:00
Gregg Van Hove
1923461b09 Ignore more browser fields when formatting Errors
- description from IE
- column from Safari
2018-02-27 09:52:19 -08:00
Gregg Van Hove
71116d3957 don't lock to 2.99 in dev 2018-02-27 09:33:10 -08:00
Gregg Van Hove
63cc7cafc8 Use Jasmine's arrayContains, instead of includes for better support 2018-02-26 17:57:37 -08:00
Gregg Van Hove
fdecf02472 Merge branch 'print_exception_properties' of https://github.com/jbunton-atlassian/jasmine into jbunton-atlassian-print_exception_properties
- Merges #1516 from @jbunton-atlassian
2018-02-26 17:48:28 -08:00
Gregg Van Hove
11f4d894a6 Merge branch 'node-load-errors'
- See #1519
2018-02-26 16:44:45 -08:00
James Bunton
1149d4edde Use j$.pp instead of JSON.stringify() for pretty printing 2018-02-27 10:22:06 +11:00
James Bunton
9ee85c35d2 Remove duplicate ignored property 2018-02-27 10:21:50 +11:00
Steve Gravrock
0367ca5294 Merge branch 'patch-closing-statement' of https://github.com/Sylhare/jasmine
- Merges #1512 from @Sylhare
2018-02-23 19:17:50 -08:00
James Bunton
763a83c833 Display error properties for failed specs 2018-02-23 14:43:47 +11:00
sylhare
7fb53dcdfa Fixing missing semi-colons 2018-02-21 09:01:24 -05:00
sgravrock
a9a112e88f Fixed release notes link 2018-02-18 21:08:52 -08:00
sgravrock
0184808a86 Updated README for 3.0 2018-02-18 21:06:51 -08:00
Steve Gravrock
1ac2a6f608 Allow node to report load time errors
[Fixes #153466462]
2018-02-17 15:45:42 -08:00
Gregg Van Hove
785f62c7a0 Fix naming and check functions for empty/notEmpty specs 2018-02-15 17:43:03 -08:00
Gregg Van Hove
d8c154a2c6 Update empty and notEmpty specs for better IE11 support 2018-02-15 17:23:44 -08:00
Gregg Van Hove
c974c4740c Merge branch 'master' of https://github.com/sjolicoeur/jasmine into sjolicoeur-master
- Merges #1460 from @sjolicoeur
2018-02-15 16:00:33 -08:00
Gregg Van Hove
2b27bd393f Add API docs for async reporters 2018-02-15 14:36:29 -08:00
Gregg Van Hove
3b77f38188 Return <anonymous> for functions that have no actual words between keyword and (
- Also fixes a potential catastrophic backtracking if someone has
severely damaged their own `toString` during test execution.
2018-02-15 12:31:10 -08:00
Steve Gravrock
11827572d3 Moved toHaveClass matcher into core so that it can be used in Karma
- Fixes #1503
2018-02-13 17:09:42 -08:00
Gregg Van Hove
8326ecf919 Merge branch 'deprecation-object' of https://github.com/UziTech/jasmine into UziTech-deprecation-object
- Merges #1498 from @UziTech
2018-02-13 16:57:24 -08:00
Gregg Van Hove
cd6a0de852 Merge pull request #1505 from codetriage-readme-bot/codetriage-badge
Add CodeTriage badge to jasmine/jasmine
2018-02-13 09:48:37 -08:00
codetriage-readme-bot
148d94558d Add CodeTriage badge to jasmine/jasmine
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 8 months ago, [alopezsanchez](https://github.com/alopezsanchez) added this project to CodeTriage in order to start contributing. Since then, 2 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-13 10:29:49 -06:00
Gregg Van Hove
83beca6899 Merge branch '2.99-patch' 2018-02-09 09:32:09 -08:00
Gregg Van Hove
3c6308f1dc Don't include the specs in the ruby gem
- Bump to 2.99.2 for gem
2018-02-09 09:22:35 -08:00
Tony Brix
6193bc113b throw errors 2018-02-08 15:12:14 -06:00
Gregg Van Hove
fa6a80b76e Merge branch 'master' of https://github.com/aptx4869/jasmine into aptx4869-master
- Merges #1501 from @aptx4869
2018-02-08 10:22:36 -08:00
Gregg Van Hove
c861f6c6c2 Merge pull request #1499 from bcaudan/patch-1
Fix release note typo
2018-02-08 10:16:57 -08:00
aptx4869
4fcd4099ad Resolve merge conflict
Fixes #1500
2018-02-08 15:07:29 +08:00
Bastien Caudan
1d495587ff Fix release note typo 2018-02-08 08:02:13 +01:00
Tony Brix
c859128537 add tests 2018-02-07 23:58:26 -06:00
Tony Brix
a8a5b839ab allow adding a deprecation object 2018-02-07 22:44:32 -06:00
Gregg Van Hove
4e5d947faa Also lock for selenium runner 2018-02-07 14:58:14 -08:00
Gregg Van Hove
c2603efeb4 Specify Jasmine Gem 2.99 tag for bundle install 2018-02-07 14:55:28 -08:00
Gregg Van Hove
fbec3cc230 Only show deprecation for catch exceptions if you tell Jasmine not to catch
- Fixes #1497
2018-02-07 14:47:10 -08:00
Gregg Van Hove
1acbd1ef96 Add notes for environments that have lost support
- #1495
2018-02-07 09:19:33 -08:00
Gregg Van Hove
3d8e379fa6 bump dev dependency for npm 2018-02-06 15:37:21 -08:00
Gregg Van Hove
55267e11f6 Make sure ruby version is a string when passing to sauce labs 2018-02-06 13:37:12 -08:00
Gregg Van Hove
09a6e3714a Bump travis ruby version 2018-02-06 12:29:12 -08:00
Gregg Van Hove
8ec4d54685 no longer run specs for docs in CI 2018-02-06 11:54:25 -08:00
Gregg Van Hove
516fe68759 Merge branch '3.0-features' 2018-02-06 11:22:41 -08:00
Gregg Van Hove
4530f9431f Generate combined file with new version numbers 2018-02-06 10:33:39 -08:00
Gregg Van Hove
d4b76a4d3b version bump to 3.0 2018-02-06 09:33:49 -08:00
Gregg Van Hove
764d58a7f5 Merge branch 'master' into 3.0-features
- cleaning up 2.99 deprecations
2018-02-06 09:31:51 -08:00
Gregg Van Hove
9911d37f06 bump version to 2.99 2018-02-05 16:57:51 -08:00
Gregg Van Hove
32f99ef99d Use Jasmine's arrayContains to look for duplicate deprecations
[#154746527]
2018-02-05 14:24:14 -08:00
Gregg Van Hove
c142490c69 Add deprecation messages for things that will change/break in 3.0
[#154746527]
2018-02-05 14:01:46 -08:00
Gregg Van Hove
24bf3489dc Display deprecation warnings in HTML reporter
- Also no longer check for stack since IE doesn't do that

[#154746527]
2018-02-05 12:11:36 -08:00
Gregg Van Hove
5afe1222f4 Add ability to report deprecation warnings from within the suite
[#154746527]
2018-02-05 11:19:15 -08:00
Gregg Van Hove
274011ed03 Merge branch 'master' into 3.0-features 2018-02-02 16:33:38 -08:00
Gregg Van Hove
42e00b3bc5 Remove node modules from python wheel, and update languages
[finishes #87860474]
2018-01-31 14:23:32 -08:00
Gregg Van Hove
0eca06a33b Now pass a navigation helper to HtmlReporter instead of click handlers 2018-01-30 14:30:28 -08:00
Gregg Van Hove
84953ec210 stop spec on failure should not default to true 2018-01-30 11:48:25 -08:00
Gregg Van Hove
e15f273f06 Replace old "catch exceptions" logic with proper fail fast with error reporting
- Option is called stopOnSpecFailure

[#85966014]
- See #414
- See jasmine/jasmine-npm#16
2018-01-30 11:36:56 -08:00
Gregg Van Hove
e908b67b19 Move explicit fail spec out of mock clock context and re-add the afterAll for IEs 2018-01-29 17:05:54 -08:00
Gregg Van Hove
46cc48ccfa Detect an Error passed to done and add an expectation failure
- See #567
2018-01-29 16:46:30 -08:00
Gregg Van Hove
262a2fe674 Generate compiled jasmine.js for async reporters work 2018-01-29 14:02:02 -08:00
Gregg Van Hove
50cd6fdd68 Allow reporter callbacks to be asynchronous
[finishes #154673961]
- Fixes #842

Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-29 11:55:41 -08:00
Gregg Van Hove
341c6df6ea Fix HTML reporter display for excluded specs 2018-01-29 10:00:15 -08:00
Elenore Bastian
3df9cc26d4 Update css for new reporter status
Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-26 15:27:35 -08:00
Gregg Van Hove
6b156ca6d1 Unify status for xdescribe and xit
- Ensure *All's only execute if at least one child will run
- Specs will report a status of `excluded` instead of disabled

[finishes #153967580]
- #1418

Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-25 16:17:31 -08:00
Elenore Bastian
07996b567f Suite level errors are reported in failures list
[#150118881]

Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-23 15:39:11 -08:00
Gregg Van Hove
9a96396f65 Generate jasmine.js for suite reporting changes
Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-23 14:38:40 -08:00
Elenore Bastian
12a47f05bf Suite level errors all report the same way (on suiteDone)
- For `beforeAll`, `afterAll`, and declaration errors

[#150118881] #1409

Signed-off-by: Gregg Van Hove <gvanhove@pivotal.io>
2018-01-23 10:15:28 -08:00
Gregg Van Hove
414e03bded Setup createSpy in all specs where needed and finish renaming params
Signed-off-by: Elenore Bastian <ebastian@pivotal.io>
2018-01-22 14:21:52 -08:00
Gregg Van Hove
038ab87252 Merge branch 'custom-spy-strategy' into 3.0-features 2018-01-22 12:12:59 -08:00
Gregg Van Hove
f20f78f82b Don't clobber previous custom plans with later plans
[finishes #37288941]
2018-01-22 12:10:24 -08:00
Gregg Van Hove
e2a191b116 Refactor QueueRunner and remove references to functions that Jasmine is done with
[finishes #56030214]
2018-01-11 17:20:13 -08:00
Steve Gravrock
cf2f922e30 Merge branch 'master' into 3.0-features 2018-01-10 15:28:55 -08:00
Steve Gravrock
170a6dce76 Made naming somewhat less confusing 2018-01-10 09:00:09 -08:00
Steve Gravrock
4934e420b2 Allow adding custom spy strategies
[#37288941]
2018-01-10 08:59:19 -08:00
Steve Gravrock
1085914a76 Extracted a SpyFactory to slim Env down a bit 2018-01-09 13:32:28 -08:00
Steve Gravrock
6f119c4e5a Moved createSpy to env so it can be stateful 2018-01-09 10:16:02 -08:00
Steve Gravrock
298b5ba127 Moved createSpyObj to env so it can be stateful 2018-01-09 09:53:45 -08:00
Steve Gravrock
16e07a0e99 Add the ability to specify the strategy to use for a spy based on which parameters are passed
[Finishes #92260826]
2018-01-03 08:49:34 -08:00
Steve Gravrock
f38527ff15 Removed IE 8 compatibility cruft from HtmlReporterSpec 2017-12-19 11:29:21 -08:00
Steve Gravrock
d742ada71d Added links to re-run the suites containing a failing spec
[Finishes #25508053]
2017-12-19 11:29:18 -08:00
Steve Gravrock
ef9f82a17d Merge branch 'master' into 3.0-features 2017-12-18 09:48:17 -08:00
Gregg Van Hove
bdbaebc045 Update contributing for new naming of jasmineUnderTest 2017-12-11 17:24:38 -08:00
Steve Gravrock
2d33765cbf Dogfood the toHaveClass matcher
[#153567695]
2017-12-11 16:00:29 -08:00
Steve Gravrock
bb0992bf5f Added a toHaveClass matcher
[#153567695]
2017-12-11 15:59:59 -08:00
Steve Gravrock
ac5d8708b9 More informative pretty-printing of DOM elements
[Finishes ##153562618]
2017-12-11 08:25:13 -08:00
Steve Gravrock
eb93d38294 Allow jasmine-npm to handle its own load errors
[Fixes #153466462]
2017-12-08 09:17:10 -08:00
sjolicoeur
d90e20eb15 Added matchers: truthy, falsy, empty and notEmpty 2017-12-07 17:49:16 -08:00
Steve Gravrock
d16aa550cb Treat random= as a no-op rather than disabling randomization
[#109197518]
2017-12-01 08:45:58 -08:00
Steve Gravrock
2200dd084d Fixed build 2017-12-01 08:34:12 -08:00
Steve Gravrock
98ead94c51 Fixed spec failure on Chrome 2017-12-01 08:28:55 -08:00
Gregg Van Hove
21655a82c9 Use prototype for spy strategy for better memory management
- Also convert `identity` to a property from a method
2017-11-30 17:30:20 -08:00
Steve Gravrock
a63172f53f expect(null).toEqual(jasmine.any(Object)) no longer passes
[Finishes #153181443]
Fixes #1255.
2017-11-29 08:10:01 -08:00
Steve Gravrock
9619acf91f Extracted the predicate version of toThrowError into its own matcher
This simplifies the signature of each matcher to something that jsdoc
can actually handle.

[Finishes #20622765]
2017-11-28 14:30:06 -08:00
Gregg Van Hove
b7e4c1e779 Remove console.js altogether
[#80410262]
2017-11-21 17:27:21 -08:00
Gregg Van Hove
e5ada1d010 Add safari 10 and update readme to include edge 2017-11-20 17:24:52 -08:00
Steve Gravrock
d35b65cf79 Set version to 3.0.0-pre 2017-11-17 14:28:20 -08:00
Steve Gravrock
db615e4186 Determine overall status in core, not reporters
[#92261606]
[#78679648]
2017-11-17 14:24:12 -08:00
Steve Gravrock
5906a2c05c Filter Jasmine frames from stack traces
[Finishes #2644992]
2017-11-13 15:49:01 -08:00
Steve Gravrock
59ad217954 Fixed bad travis.yml merge
Re-removed IE 8, IE 9, and Node 0.12.x from the testing matrix
2017-11-10 10:47:08 -08:00
Steve Gravrock
b0ec95c472 Merge branch 'master' into 3.0-features 2017-11-10 10:26:14 -08:00
Steve Gravrock
a42f28c734 Removed checks for PhantomJS 1
v2 has been out for a long time, and v1 can no longer be easily installed.
2017-11-09 07:04:06 -08:00
Steve Gravrock
d58f3dac56 Test against multiple Node versions on Travis 2017-11-08 09:17:55 -08:00
Steve Gravrock
676689b063 Test against Node 4.x, not 0.10.x 2017-11-08 09:11:41 -08:00
Steve Gravrock
aaf226b9e3 Removed spec guards for versions of Safari we no longer support 2017-11-08 08:30:35 -08:00
Steve Gravrock
419470e9df Removed support for IE <10
[#150527985]
2017-11-08 08:30:22 -08:00
Steve Gravrock
1526d5e2a8 Treat afterAll errors at any level as failures
[Finishes #152492514]
2017-11-07 20:48:23 -08:00
Steve Gravrock
a3cb010971 Removed remaining traces of the obsolete console reporter
[#80410262]
2017-11-07 20:09:04 -08:00
Steve Gravrock
278ef9228b Removed obsolete console reporter from core
Anyone who was still using this should use the one in jasmine-npm
instead.

[Finishes #80410262]
2017-11-07 12:25:47 -08:00
Steve Gravrock
82eeed3c85 Improved reporting of load errors and afterAll errors
- Pass file and line number to reporters when present
- Show file and line number in the HTML reporter when present
- Visually separate adjacent errors in the HTML reporter

[#24901981]
2017-11-04 10:28:42 -07:00
Steve Gravrock
ae9b95269c Load error handling doesn't depend on browser features, so test it everywher
[#24901981]
2017-11-02 18:17:40 -07:00
Steve Gravrock
26a7bc6acf Report loading errors as loading errors, not afterAll errors
[#24901981]
2017-11-01 14:09:29 -07:00
Steve Gravrock
7b8edcb401 HTML reporter reports overall failure if there are any global errors
[#24901981]
2017-11-01 11:44:58 -07:00
Steve Gravrock
395b2b2d97 Test against Edge 2017-10-31 21:50:42 -07:00
Steve Gravrock
bd250f27c7 Fail if error events (e.g. syntax errors) occur during loading
[#24901981]
2017-10-31 21:16:00 -07:00
Steve Gravrock
12ed3bfacd Allow use of a predicate function to validate thrown exceptions
[Finishes #20622765]
2017-10-30 08:51:25 -07:00
Steve Gravrock
324ad0073e Refactored toThrowMatching to facilitate adding more strategies
* Extracted sub-matchers for the two major existing strategies
  (matching all errors, and matching by type and/or message)
* Reduced the use of mutable state
2017-10-30 08:51:25 -07:00
Steve Gravrock
9f7a6ef061 Check truthiness of toThrowError args, not arg count
This enables some useful simplifications at the cost of making it
impossible (for now) to expect a function to throw an error with a falsy
message.

[#20622765]
2017-10-30 08:51:25 -07:00
sgravrock
908583c49b Point CodeClimate at the right repo 2017-10-30 08:51:25 -07:00
Steve Gravrock
e31db20ec7 Default to running tests in random order
[Finishes #109197518]
2017-10-27 08:50:40 -07:00
293 changed files with 32881 additions and 9463 deletions

205
.circleci/config.yml Normal file
View File

@@ -0,0 +1,205 @@
# Run tests against supported Node versions, and (except for pull requests)
# against supported browsers.
version: 2.1
orbs:
node: circleci/node@3.0.0
executors:
node16:
docker:
- image: cimg/node:16.1.0-browsers
working_directory: ~/workspace
node14:
docker:
- image: circleci/node:14
working_directory: ~/workspace
node12:
docker:
- image: circleci/node:12
working_directory: ~/workspace
node10:
docker:
- image: circleci/node:10
working_directory: ~/workspace
jobs:
build:
parameters:
executor:
type: executor
executor: << parameters.executor >>
steps:
- checkout
- run:
name: Report Node and NPM versions
command: echo "Using Node $(node --version) and NPM $(npm --version)"
- run:
name: Install dependencies
command: npm install
- run:
name: Build
command: npm run build
- persist_to_workspace:
root: .
paths:
- .
test_node: &test_node
parameters:
executor:
type: executor
executor: << parameters.executor >>
steps:
- attach_workspace:
at: .
- run:
name: Run tests
command: npm test
test_browsers: &test_browsers
executor: node14
environment:
SKIP_JASMINE_BROWSER_FLAKES: "true"
steps:
- attach_workspace:
at: .
- run:
name: Install Sauce Connect
command: |
cd /tmp
curl https://saucelabs.com/downloads/sc-4.6.4-linux.tar.gz | tar zxf -
chmod +x sc-4.6.4-linux/bin/sc
mkdir ~/workspace/bin
cp sc-4.6.4-linux/bin/sc ~/workspace/bin
~/workspace/bin/sc --version
- run:
name: Run tests
command: |
# Do everything in one step because Sauce Connect won't exit
# cleanly if we kill it from a different step than it started in.
export PATH=$PATH:$HOME/workspace/bin
export SAUCE_TUNNEL_IDENTIFIER=$CIRCLE_BUILD_NUM
scripts/start-sauce-connect sauce-pidfile
set +o errexit
scripts/run-all-browsers
exitcode=$?
set -o errexit
scripts/stop-sauce-connect $(cat sauce-pidfile)
exit $exitcode
test_browser_flakes:
<<: *test_browsers
environment:
SKIP_JASMINE_BROWSER_FLAKES: "false"
workflows:
version: 2
cron:
triggers:
- schedule:
# Times are UTC.
cron: "0 11 * * *"
filters:
branches:
only:
- main
- "3.99"
- "4.0"
jobs:
- build:
executor: node16
name: build_node_16
- build:
executor: node14
name: build_node_14
- build:
executor: node12
name: build_node_12
- build:
executor: node10
name: build_node_10
- test_node:
executor: node16
name: test_node_16
requires:
- build_node_16
- test_node:
executor: node12
name: test_node_12
requires:
- build_node_12
- test_node:
executor: node10
name: test_node_10
requires:
- build_node_10
- test_browsers:
requires:
- build_node_14
filters:
branches:
ignore: /pull\/.*/ # Don't run on pull requests.
push:
jobs:
- build:
executor: node16
name: build_node_16
- build:
executor: node14
name: build_node_14
- build:
executor: node12
name: build_node_12
- build:
executor: node10
name: build_node_10
- test_node:
executor: node16
name: test_node_16
requires:
- build_node_16
- test_node:
executor: node14
name: test_node_14
requires:
- build_node_14
- test_node:
executor: node12
name: test_node_12
requires:
- build_node_12
- test_node:
executor: node10
name: test_node_10
requires:
- build_node_10
- test_browsers:
requires:
- build_node_14
filters:
branches:
ignore: /pull\/.*/ # Don't run on pull requests.
browser-flakes:
triggers:
- schedule:
# Times are UTC.
cron: "0 10 * * *"
filters:
branches:
only:
- browser-flakes
jobs:
- build:
executor: node14
name: build_node_14
- test_browser_flakes:
requires:
- build_node_14
filters:
branches:
ignore: /pull\/.*/ # Don't run on pull requests.

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
* text=auto eol=lf
*.png -text

View File

@@ -1,6 +1,12 @@
# 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 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.
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 help needed](https://github.com/jasmine/jasmine/labels/help%20needed)
should have enough detail to get started.
## Links
@@ -17,7 +23,7 @@ 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 # Fetch changes not present in your local repository
git merge upstream/master # Sync local master with upstream repository
git merge upstream/main # Sync local main with upstream 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
@@ -30,14 +36,13 @@ Once you've pushed a feature branch to your forked repo, you're ready to open a
### Directory Structure
* `/src` contains all of the source files
* `/src/console` - Node.js-specific files
* `/src/core` - generic source files
* `/src/html` - browser-specific files
* `/spec` contains all of the tests
* mirrors the source directory
* there are some additional files
* `/dist` contains the standalone distributions as zip files
* `/lib` contains the generated files for distribution as the Jasmine Rubygem and the Python package
* `/lib` contains the compiled copy of Jasmine. This is used to self-test and
distributed as the `jasmine-core` Node, Ruby, and Python packages.
### Self-testing
@@ -45,76 +50,71 @@ Note that Jasmine tests itself. The files in `lib` are loaded first, defining th
The tests should always use `jasmineUnderTest` to refer to the objects and functions that are being tested. But the tests can use functions on `jasmine` as needed. _Be careful how you structure any new test code_. Copy the patterns you see in the existing code - this ensures that the code you're testing is not leaking into the `jasmine` reference and vice-versa.
### `boot.js`
### `boot0.js` and `boot1.js`
__This is new for Jasmine 2.0.__
This file does all of the setup necessary for Jasmine to work. It loads all of the code, creates an `Env`, attaches the global functions, and builds the reporter. It also sets up the execution of the `Env` - for browsers this is in `window.onload`. While the default in `lib` is appropriate for browsers, projects may wish to customize this file.
For example, for Jasmine development there is a different `dev_boot.js` for Jasmine development that does more work.
These files file does all of the setup necessary for Jasmine to work in a
browser. They load all of the code, create an `Env`, attach the global
functions, and build the reporter. It also sets up the execution of the
`Env` - for browsers this is in `window.onload`. While the default in `lib`
is appropriate for browsers, projects may wish to customize this file.
### Compatibility
* Browser Minimum
* IE8
* Firefox 3.x
* Chrome ??
* Safari 5
Jasmine runs in both Node and browsers, including some older browsers that do
not support the latest JavaScript features. See the README for the list of
currently supported environments.
## Development
All source code belongs in `src/`. The `core/` directory contains the bulk of Jasmine's functionality. This code should remain browser- and environment-agnostic. If your feature or fix cannot be, as mentioned above, please degrade gracefully. Any code that should only be in a non-browser environment should live in `src/console/`. Any code that depends on a browser (specifically, it expects `window` to be the global or `document` is present) should live in `src/html/`.
All source code belongs in `src/`. The `core/` directory contains the bulk of Jasmine's functionality. This code should remain browser- and environment-agnostic. If your feature or fix cannot be, as mentioned above, please degrade gracefully. Any code that depends on a browser (specifically, it expects `window` to be the global or `document` is present) should live in `src/html/`.
### Install Dependencies
### Install Dev Dependencies
Jasmine Core relies on Ruby and Node.js.
Jasmine Core relies on Node.js.
To install the Ruby dependencies, you will need Ruby, Rubygems, and Bundler available. Then:
To install the Node dependencies, you will need Node.js and npm.
$ bundle
...will install all of the Ruby dependencies. If the ffi gem fails to build its native extensions, you may need to manually install some system dependencies. On Ubuntu:
$ apt-get install gcc ruby ruby-dev libxml2 libxml2-dev libxslt1-dev
...should get you to the point that `bundle` can install everything.
To install the Node dependencies, you will need Node.js, Npm, and [Grunt](http://gruntjs.com/), the [grunt-cli](https://github.com/gruntjs/grunt-cli) and ensure that `grunt` is on your path.
$ npm install --local
$ npm install
...will install all of the node modules locally. Now run
$ grunt
$ npm test
...if you see that JSHint runs, your system is ready.
...you should see tests run and eslint checking formatting.
### How to write new Jasmine code
Or, How to make a successful pull request
* _Do not change the public interface_. Lots of projects depend on Jasmine and if you aren't careful you'll break them
* _Be environment agnostic_ - server-side developers are just as important as browser developers
* _Be browser agnostic_ - if you must rely on browser-specific functionality, please write it in a way that degrades gracefully
* _Write specs_ - Jasmine's a testing framework; don't add functionality without test-driving it
* _Write code in the style of the rest of the repo_ - Jasmine should look like a cohesive whole
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and JSHint - your contribution shouldn't break Jasmine for other users
* _Do not change the public interface_. Lots of projects depend on Jasmine and
if you aren't careful you'll break them.
* _Be environment agnostic_ - server-side developers are just as important as
browser developers.
* _Be browser agnostic_ - if you must rely on browser-specific functionality,
please write it in a way that degrades gracefully.
* _Write specs_ - Jasmine's a testing framework. Don't add functionality
without test-driving it.
* _Write code in the style of the rest of the repo_ - Jasmine should look like
a cohesive whole.
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and
ESLint. Your contribution shouldn't break Jasmine for other users.
Follow these tips and your pull request, patch, or suggestion is much more likely to be integrated.
### Running Specs
Jasmine uses the [Jasmine Ruby gem](http://github.com/jasmine/jasmine-gem) to test itself in browser.
Be sure to run the tests in at least one supported Node version and at least a
couple of supported browsers. It's also a good idea to run the tests in Internet
Explorer if you've touched code in `src/html`, if your change involves newer
JavaScript language/runtime features, or if you're unfamiliar with writing code
for older browsers. To run the tests in Node, simply use `npm test` as described
above. To run the tests in a browser, run `npm run serve` and then visit
`http://localhost:8888`.
$ bundle exec rake jasmine
If you have the necessary Selenium drivers installed, you can also use Jasmine's
CI tooling:
...and then visit `http://localhost:8888` to run specs.
Jasmine uses the [Jasmine NPM package](http://github.com/jasmine/jasmine-npm) to test itself in a Node.js/npm environment.
$ grunt execSpecsInNode
...and then the results will print to the console. All specs run except those that expect a browser (the specs in `spec/html` are ignored).
$ JASMINE_BROWSER=<name of browser> node spec/support/ci.js
The easiest way to run the tests in **Internet Explorer** is to run a VM that has IE installed. It's easy to do this with VirtualBox.
@@ -123,16 +123,16 @@ The easiest way to run the tests in **Internet Explorer** is to run a VM that ha
1. Unzip the downloaded archive. There should be an OVA file inside.
1. In VirtualBox, choose `File > Import Appliance` and select the OVA file. Accept the default settings in the dialog that appears. Now you have a Windows VM!
1. Run the VM and start IE.
1. With `bundle exec rake jasmine` running on your host machine, navigate to `http://10.0.2.2:8888` in IE.
1. With `npm run serve` running on your host machine, navigate to `http://<your IP address>:8888` in IE.
## Before Committing or Submitting a Pull Request
1. Ensure all specs are green in browser *and* node
1. Ensure JSHint is green with `grunt jshint`
1. Build `jasmine.js` with `grunt buildDistribution` and run all specs again - this ensures that your changes self-test well
1. Ensure all specs are green in browser *and* node.
1. Ensure eslint and prettier are clean as part of your `npm test` command. You can run `npm run cleanup` to have prettier re-write the files.
1. Build `jasmine.js` with `npm run build` and run all specs again - this ensures that your changes self-test well.
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
* When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into master
* When we accept your pull request, we will generate these files as a separate commit and merge the entire branch into main
Note that we use Travis for Continuous Integration. We only accept green pull requests.
Note that we use Circle CI for Continuous Integration. We only accept green pull requests.

View File

@@ -3,9 +3,12 @@
- When in doubt, create an issue here.
- If you have an issue with the Jasmine docs, file an issue in the docs repo
here: https://github.com/jasmine/jasmine.github.io
- If you have an issue with TypeScript typings, start a discussion at
[DefinitelyTpyed](https://github.com/DefinitelyTyped/DefinitelyTyped/discussions/new?category=issues-with-a-types-package)
- This repository is for the core Jasmine framework
- If you are using a test runner that wraps Jasmine, consider filing an issue with that library if appropriate:
- [Jasmine npm](https://github.com/jasmine/jasmine-npm/issues)
- [Jasmine browser runner](https://github.com/jasmine/jasmine-browser/issues)
- [Jasmine gem](https://github.com/jasmine/jasmine-gem/issues)
- [Jasmine py](https://github.com/jasmine/jasmine-py/issues)
- [Gulp Jasmine Browser](https://github.com/jasmine/gulp-jasmine-browser/issues)

2
.gitignore vendored
View File

@@ -12,6 +12,7 @@ site/
tags
Gemfile.lock
package-lock.json
yarn.lock
pkg/*
.sass-cache/*
src/html/.sass-cache/*
@@ -24,3 +25,4 @@ build/
dist
nbproject/
*.iml
.envrc

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "pages"]
path = pages
url = https://github.com/pivotal/jasmine.git

View File

@@ -1,9 +0,0 @@
{
"bitwise": true,
"curly": true,
"immed": true,
"newcap": true,
"trailing": true,
"loopfunc": true,
"quotmark": "single"
}

View File

@@ -1,28 +0,0 @@
dist/
grunt/
node_modules
pkg/
release_notes/
spec/
src/
Gemfile
Gemfile.lock
Rakefile
jasmine-core.gemspec
.bundle/
.gitignore
.gitmodules
.idea
.jshintrc
.rspec
.sass-cache/
.travis.yml
*.sh
*.py
Gruntfile.js
lib/jasmine-core.rb
lib/jasmine-core/boot/
lib/jasmine-core/spec
lib/jasmine-core/version.rb
lib/jasmine-core/*.py
sauce_connect.log

View File

@@ -1,75 +0,0 @@
language: ruby
cache: bundler
sudo: false
rvm: 2.2.2
script: $TEST_COMMAND
env:
global:
- USE_SAUCE=true
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- TEST_COMMAND="bash travis-core-script.sh"
- JASMINE_BROWSER="firefox"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- secure: WSPWhlnC4mWSnSPquX+m1/BCu5ch5NygkaHuM2Nea7lD8oS3XLX8QncZZAsQ4lnNfqoDDuBOizG0AESiqNvE4y6x5qvLLTS6q+ce255ZEMZ71TBdZgDEEvGMEjOPPsVXiXyTQOP1lwOPlrbZvaPgWV7e11KIBab6DfFcQpnvDgo=
- secure: SW7CJhZnwaNT749Gdnhvqb5rbXlAOsygUAzh9qhtyvbqXKkmJdBIEsO01YF6pbju1X2twE9JvWCOxeZju43NgQChJlPsGbjY2j3k/TdQeTAJesQe2K7ytwghunI30gjEovtRH0T3w1EmcKPH8yj5eBIcB2OYoJHx8KEC7e68q1g=
addons:
sauce_connect: true
matrix:
include:
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v0.12.18"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v4"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v8"
- env:
- USE_SAUCE=false
- TEST_COMMAND="bash travis-node-script.sh v9"
- env:
- JASMINE_BROWSER="safari"
- SAUCE_OS="OS X 10.11"
- SAUCE_BROWSER_VERSION=9
- env:
- JASMINE_BROWSER="safari"
- 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="internet explorer"
- SAUCE_OS="Windows 8.1"
- SAUCE_BROWSER_VERSION=11
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 8"
- SAUCE_BROWSER_VERSION=10
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=9
- env:
- JASMINE_BROWSER="internet explorer"
- SAUCE_OS="Windows 7"
- SAUCE_BROWSER_VERSION=8
- env:
- JASMINE_BROWSER="chrome"
- SAUCE_OS="Linux"
- SAUCE_BROWSER_VERSION=''
- env:
- JASMINE_BROWSER="phantomjs"
- USE_SAUCE=false
- env:
- USE_SAUCE=false
- JASMINE_BROWSER="phantomjs"
- TEST_COMMAND="bash travis-docs-script.sh"

View File

@@ -1,9 +1,2 @@
source 'https://rubygems.org'
gem "jasmine", :git => 'https://github.com/jasmine/jasmine-gem.git'
# gem "jasmine", path: "../jasmine-gem"
gemspec
gem "jasmine_selenium_runner", :github => 'jasmine/jasmine_selenium_runner'
gem "anchorman"

View File

@@ -4,17 +4,17 @@ module.exports = function(grunt) {
grunt.initConfig({
pkg: pkg,
jshint: require('./grunt/config/jshint.js'),
concat: require('./grunt/config/concat.js'),
compass: require('./grunt/config/compass.js'),
compress: require('./grunt/config/compress.js')
sass: require('./grunt/config/sass.js'),
compress: require('./grunt/config/compress.js'),
cssUrlEmbed: require('./grunt/config/cssUrlEmbed.js')
});
require('load-grunt-tasks')(grunt);
grunt.loadTasks('grunt/tasks');
grunt.registerTask('default', ['jshint:all']);
grunt.registerTask('default', ['sass:dist', "cssUrlEmbed"]);
var version = require('./grunt/tasks/version.js');
@@ -25,11 +25,9 @@ module.exports = function(grunt) {
grunt.registerTask('buildDistribution',
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
[
'compass',
'jshint:beforeConcat',
'concat',
'jshint:afterConcat',
'build:copyVersionToGem'
'sass:dist',
"cssUrlEmbed",
'concat'
]
);

View File

@@ -1,4 +1,5 @@
recursive-include . *.py
prune node_modules
include lib/jasmine-core/*.js
include lib/jasmine-core/*.css
include images/*.png

View File

@@ -1,4 +1,4 @@
Copyright (c) 2008-2017 Pivotal Labs
Copyright (c) 2008-2019 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,66 +1,73 @@
<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/main/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
[![Build Status](https://travis-ci.org/jasmine/jasmine.svg?branch=master)](https://travis-ci.org/jasmine/jasmine)
[![Build Status](https://circleci.com/gh/jasmine/jasmine.svg?style=shield)](https://circleci.com/gh/jasmine/jasmine)
[![Open Source Helpers](https://www.codetriage.com/jasmine/jasmine/badges/users.svg)](https://www.codetriage.com/jasmine/jasmine)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield)
=======
**A JavaScript Testing Framework**
# A JavaScript Testing Framework
Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, [Node.js](http://nodejs.org) projects, or anywhere that JavaScript can run.
Documentation & guides live here: [http://jasmine.github.io](http://jasmine.github.io/)
For a quick start guide of Jasmine 2.x, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html)
Upgrading from Jasmine 1.x? Check out the [2.0 release notes](https://github.com/jasmine/jasmine/blob/v2.0.0/release_notes/20.md) for a list of what's new (including breaking interface changes). You can also read the [upgrade guide](http://jasmine.github.io/2.0/upgrading.html).
For a quick start guide of Jasmine, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html).
## Contributing
Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/master/.github/CONTRIBUTING.md)
Please read the [contributors' guide](https://github.com/jasmine/jasmine/blob/main/.github/CONTRIBUTING.md).
## Installation
For the Jasmine NPM module:<br>
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm)
[https://github.com/jasmine/jasmine-npm](https://github.com/jasmine/jasmine-npm).
For the Jasmine browser runner:<br>
[https://github.com/jasmine/jasmine-browser](https://github.com/jasmine/jasmine-browser).
For the Jasmine Ruby Gem:<br>
[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem)
For the Jasmine Python Egg:<br>
[https://github.com/jasmine/jasmine-py](https://github.com/jasmine/jasmine-py)
For the Jasmine headless browser gulp plugin:<br>
[https://github.com/jasmine/gulp-jasmine-browser](https://github.com/jasmine/gulp-jasmine-browser)
[https://github.com/jasmine/jasmine-gem](https://github.com/jasmine/jasmine-gem).
To install Jasmine standalone on your local box (where **_{#.#.#}_** below is substituted by the release number downloaded):
* 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 the dist to your project directory - `mv jasmine/dist/jasmine-standalone-{#.#.#}.zip my-project/jasmine`
* Change directory - `cd my-project/jasmine`
* Unzip the dist - `unzip jasmine-standalone-{#.#.#}.zip`
* 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 the dist to your project directory. - `mv jasmine/dist/jasmine-standalone-{#.#.#}.zip my-project/jasmine`
* Change directory. - `cd my-project/jasmine`
* Unzip the dist. - `unzip jasmine-standalone-{#.#.#}.zip`
Add the following to your HTML file:
```html
<link rel="shortcut icon" type="image/png" href="jasmine/lib/jasmine-{#.#.#}/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="jasmine/lib/jasmine-{#.#.#}/jasmine.css">
<link rel="shortcut icon" type="image/png" href="lib/jasmine-{#.#.#}/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="lib/jasmine-{#.#.#}/jasmine.css">
<script type="text/javascript" src="jasmine/lib/jasmine-{#.#.#}/jasmine.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-{#.#.#}/jasmine-html.js"></script>
<script type="text/javascript" src="jasmine/lib/jasmine-{#.#.#}/boot.js"></script>
<script type="text/javascript" src="lib/jasmine-{#.#.#}/jasmine.js"></script>
<script type="text/javascript" src="lib/jasmine-{#.#.#}/jasmine-html.js"></script>
<script type="text/javascript" src="lib/jasmine-{#.#.#}/boot.js"></script>
```
## Supported environments
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, and new Internet Explorer) as well as node. To see the exact version tests are run against look at our [.travis.yml](https://github.com/jasmine/jasmine/blob/master/.travis.yml)
Jasmine tests itself across many browsers (Safari, Chrome, Firefox, Microsoft Edge, and Internet Explorer) as well as nodejs.
| Environment | Supported versions |
|-------------------|--------------------|
| Node | 10, 12, 14, 16 |
| Safari | 8-14 |
| Chrome | Evergreen |
| Firefox | Evergreen, 68, 78 |
| Edge | Evergreen |
| Internet Explorer | 10, 11 |
For evergreen browsers, each version of Jasmine is tested against the version of the browser that is available to us
at the time of release. Other browsers, as well as older & newer versions of some supported browsers, are likely to work.
However, Jasmine isn't tested against them and they aren't actively supported.
## Support
* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js)
* Send an email to the list: [jasmine-js@googlegroups.com](mailto:jasmine-js@googlegroups.com)
* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606)
* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD)
* Search past discussions: [http://groups.google.com/group/jasmine-js](http://groups.google.com/group/jasmine-js).
* Send an email to the list: [jasmine-js@googlegroups.com](mailto:jasmine-js@googlegroups.com).
* View the project backlog at Pivotal Tracker: [http://www.pivotaltracker.com/projects/10606](http://www.pivotaltracker.com/projects/10606).
* Follow us on Twitter: [@JasmineBDD](http://twitter.com/JasmineBDD).
## Maintainers
@@ -75,4 +82,8 @@ Jasmine tests itself across many browsers (Safari, Chrome, Firefox, PhantomJS, a
* [Christian Williams](mailto:antixian666@gmail.com), Cloud Foundry
* Sheel Choksi
Copyright (c) 2008-2017 Pivotal Labs. This software is licensed under the MIT License.
Copyright (c) 2008-2018 Pivotal Labs. This software is licensed under the MIT License.
## License
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_large)

View File

@@ -7,7 +7,7 @@ Follow the instructions in `CONTRIBUTING.md` during development.
### Git Rules
Please attempt to keep commits to `master` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when pushing to `master`.
Please attempt to keep commits to `main` small, but cohesive. If a feature is contained in a bunch of small commits (e.g., it has several wip commits or small work), please squash them when pushing to `main`.
### Version
@@ -28,31 +28,38 @@ When jasmine-core revs its major or minor version, the binding libraries should
When ready to release - specs are all green and the stories are done:
1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly
1. Update the version in `package.json` to a release candidate
1. Update any links or top-level landing page for the Github Pages
1. Update the release notes in `release_notes` - use the Anchorman gem to generate the markdown file and edit accordingly. Include a list of supported environments.
1. Update the version in `package.json`
1. Run `npm run build`.
1. Copy version to the Ruby gem with `grunt build:copyVersionToGem`
### Commit and push core changes
1. Run the browser tests using `scripts/run-all-browsers`.
1. Commit release notes and version changes (jasmine.js, version.rb, package.json)
1. Push
1. Wait for Circle CI to go green
### Build standalone distribution
1. Build the standalone distribution with `grunt buildStandaloneDist`
1. This will generate `dist/jasmine-standalone-<version>.zip`, which you will upload later (see "Finally" below).
### Release the Python egg
### Release the core Ruby gem
1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release. See below.
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally.
### Release the core Python egg
Install [twine](https://github.com/pypa/twine)
1. `python setup.py sdist`
1. `twine upload dist/jasmine-core-<version>.tar.gz` You will need pypi credentials to upload the egg.
### Release the Ruby gem
1. Copy version to the Ruby gem with `grunt build:copyVersionToGem`
1. __NOTE__: You will likely need to point to a local jasmine gem in order to run tests locally. _Do not_ push this version of the Gemfile.
1. __NOTE__: You will likely need to push a new jasmine gem with a dependent version right after this release.
1. Push these changes to GitHub and verify that this SHA is green
1. `rake release` - tags the repo with the version, builds the `jasmine-core` gem, pushes the gem to Rubygems.org. In order to release you will have to ensure you have rubygems creds locally.
### Release the NPM
### Release the core NPM module
1. Run the tests on Windows. (CI only tests on Linux.)
1. `npm adduser` to save your credentials locally
1. `npm publish .` to publish what's in `package.json`
@@ -60,15 +67,35 @@ Install [twine](https://github.com/pypa/twine)
Probably only need to do this when releasing a minor version, and not a patch 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`
1. `rake update_edge_jasmine`
1. `npm run jsdoc`
1. `rake release[${version}]` to copy the current edge docs to the new version
1. Commit and push.
### Release the binding libraries
#### NPM
1. Create release notes using Anchorman as above
1. In `package.json`, update both the package version and the jasmine-core dependency version
1. Commit and push.
1. Wait for Circle CI to go green again.
1. Run the tests on Windows locally.
1. `grunt release `. (Note: This will publish the package by running `npm publish`.)
#### Gem
1. Create release notes using Anchorman as above
1. Update the version number in `lib/jasmine/version.rb`.
1. Update the jasmine-core dependency version in `jasmine.gemspec`.
1. Commit and push.
1. Wait for Circle CI to go green again.
1. `rake release`
### Finally
1. Visit the [Releases page for Jasmine](https://github.com/jasmine/jasmine/releases), find the tag just pushed.
1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes.
1. If it is a pre-release, mark it as such.
1. Attach the standalone zipfile
There should be a post to Pivotal Labs blog and a tweet to that link.
For each of the above GitHub repos:
1. Visit the releases page and find the tag just published.
1. Paste in a link to the correct release notes for this release. The link should reference the blob and tag correctly, and the markdown file for the notes.
1. If it is a pre-release, mark it as such.
1. For core, attach the standalone zipfile.

View File

@@ -1,18 +1,2 @@
require "bundler"
Bundler::GemHelper.install_tasks
require "json"
require "jasmine"
unless ENV["JASMINE_BROWSER"] == 'phantomjs'
require "jasmine_selenium_runner"
end
load "jasmine/tasks/jasmine.rake"
namespace :jasmine do
task :set_env do
ENV['JASMINE_CONFIG_PATH'] ||= 'spec/support/jasmine.yml'
end
end
task "jasmine:configure" => "jasmine:set_env"
task :default => "jasmine:ci"

View File

@@ -1,11 +0,0 @@
module.exports = {
jasmine: {
options: {
cssDir: 'lib/jasmine-core/',
sassDir: 'src/html',
outputStyle: 'compact',
noLineComments: true,
bundleExec: true
}
}
};

View File

@@ -2,7 +2,6 @@ var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
function root(path) { return "./" + path; }
function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
function libConsole() { return "lib/console/" }
function dist(path) { return root("dist/" + path); }
module.exports = {
@@ -30,15 +29,7 @@ module.exports = {
cwd: libJasmineCore("")
},
{
src: [
"console.js"
],
dest: standaloneLibDir,
expand: true,
cwd: libConsole()
},
{
src: [ "boot.js" ],
src: [ "boot0.js", "boot1.js" ],
dest: standaloneLibDir,
expand: true,
cwd: libJasmineCore("boot")

View File

@@ -15,7 +15,8 @@ module.exports = {
'src/html/HtmlReporter.js',
'src/html/HtmlSpecFilter.js',
'src/html/ResultsNode.js',
'src/html/QueryString.js'
'src/html/QueryString.js',
'src/html/**/*.js'
],
dest: 'lib/jasmine-core/jasmine-html.js'
},
@@ -40,17 +41,18 @@ module.exports = {
src: ['lib/jasmine-core/boot/boot.js'],
dest: 'lib/jasmine-core/boot.js'
},
boot0: {
src: ['lib/jasmine-core/boot/boot0.js'],
dest: 'lib/jasmine-core/boot0.js'
},
boot1: {
src: ['lib/jasmine-core/boot/boot1.js'],
dest: 'lib/jasmine-core/boot1.js'
},
nodeBoot: {
src: ['lib/jasmine-core/boot/node_boot.js'],
dest: 'lib/jasmine-core/node_boot.js'
},
console: {
src: [
'src/console/requireConsole.js',
'src/console/ConsoleReporter.js'
],
dest: 'lib/console/console.js'
},
options: {
banner: license(),
process: {

View File

@@ -0,0 +1,7 @@
module.exports = {
encodeWithBaseDir: {
files: {
"lib/jasmine-core/jasmine.css": ["lib/jasmine-core/jasmine.css"]
}
}
};

View File

@@ -1,11 +0,0 @@
module.exports = {
beforeConcat: ['src/**/*.js'],
afterConcat: [
'lib/jasmine-core/jasmine-html.js',
'lib/jasmine-core/jasmine.js'
],
options: {
jshintrc: '.jshintrc'
},
all: ['src/**/*.js']
};

13
grunt/config/sass.js Normal file
View File

@@ -0,0 +1,13 @@
const sass = require('sass');
module.exports = {
options: {
implementation: sass,
sourceComments: false
},
dist: {
files: {
"lib/jasmine-core/jasmine.css": "src/html/jasmine.scss"
}
}
};

View File

@@ -9,7 +9,9 @@
<script src="lib/jasmine-<%= jasmineVersion %>/jasmine.js"></script>
<script src="lib/jasmine-<%= jasmineVersion %>/jasmine-html.js"></script>
<script src="lib/jasmine-<%= jasmineVersion %>/boot.js"></script>
<script src="lib/jasmine-<%= jasmineVersion %>/boot0.js"></script>
<!-- optional: include a file here that configures the Jasmine env -->
<script src="lib/jasmine-<%= jasmineVersion %>/boot1.js"></script>
<!-- include source files here... -->
<script src="src/Player.js"></script>

View File

@@ -8,16 +8,23 @@ Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.authors = ["Gregg Van Hove"]
s.summary = %q{JavaScript BDD framework}
s.description = %q{Test your JavaScript without any framework dependencies, in any environment, and with a nice descriptive syntax.}
s.description = <<~DESC
Test your JavaScript without any framework dependencies, in any environment,
and with a nice descriptive syntax.
Jasmine for Ruby is deprecated. The direct replacment for the jasmine-core
gem is the jasmine-core NPM package. If you are also using the jasmine gem,
we recommend using the jasmine-browser-runner NPM package instead. It
supports all the same scenarios as the jasmine gem gem plus Webpacker. See
https://jasmine.github.io/setup/browser.html for setup instructions, and
https://github.com/jasmine/jasmine-gem/blob/main/release_notes/3.9.0.md
for other options.
DESC
s.email = %q{jasmine-js@googlegroups.com}
s.homepage = "http://jasmine.github.io"
s.rubyforge_project = "jasmine-core"
s.license = "MIT"
s.files = Dir.glob("./lib/**/*") + Dir.glob("./lib/jasmine-core/spec/**/*.js")
s.files = Dir.glob("./lib/**/*")
s.require_paths = ["lib"]
s.add_development_dependency "rake"
s.add_development_dependency "sauce-connect"
s.add_development_dependency "compass"
s.add_development_dependency "jasmine_selenium_runner", ">= 0.2.0"
end

View File

@@ -1,190 +0,0 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
function getJasmineRequireObj() {
if (typeof module !== 'undefined' && module.exports) {
return exports;
} else {
window.jasmineRequire = window.jasmineRequire || {};
return window.jasmineRequire;
}
}
getJasmineRequireObj().console = function(jRequire, j$) {
j$.ConsoleReporter = jRequire.ConsoleReporter();
};
getJasmineRequireObj().ConsoleReporter = function() {
var noopTimer = {
start: function(){},
elapsed: function(){ return 0; }
};
function ConsoleReporter(options) {
var print = options.print,
showColors = options.showColors || false,
onComplete = options.onComplete || function() {},
timer = options.timer || noopTimer,
specCount,
failureCount,
failedSpecs = [],
pendingCount,
ansi = {
green: '\x1B[32m',
red: '\x1B[31m',
yellow: '\x1B[33m',
none: '\x1B[0m'
},
failedSuites = [];
print('ConsoleReporter is deprecated and will be removed in a future version.');
this.jasmineStarted = function() {
specCount = 0;
failureCount = 0;
pendingCount = 0;
print('Started');
printNewline();
timer.start();
};
this.jasmineDone = function() {
printNewline();
for (var i = 0; i < failedSpecs.length; i++) {
specFailureDetails(failedSpecs[i]);
}
if(specCount > 0) {
printNewline();
var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
failureCount + ' ' + plural('failure', failureCount);
if (pendingCount) {
specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
}
print(specCounts);
} else {
print('No specs found');
}
printNewline();
var seconds = timer.elapsed() / 1000;
print('Finished in ' + seconds + ' ' + plural('second', seconds));
printNewline();
for(i = 0; i < failedSuites.length; i++) {
suiteFailureDetails(failedSuites[i]);
}
onComplete(failureCount === 0);
};
this.specDone = function(result) {
specCount++;
if (result.status == 'pending') {
pendingCount++;
print(colored('yellow', '*'));
return;
}
if (result.status == 'passed') {
print(colored('green', '.'));
return;
}
if (result.status == 'failed') {
failureCount++;
failedSpecs.push(result);
print(colored('red', 'F'));
}
};
this.suiteDone = function(result) {
if (result.failedExpectations && result.failedExpectations.length > 0) {
failureCount++;
failedSuites.push(result);
}
};
return this;
function printNewline() {
print('\n');
}
function colored(color, str) {
return showColors ? (ansi[color] + str + ansi.none) : str;
}
function plural(str, count) {
return count == 1 ? str : str + 's';
}
function repeat(thing, times) {
var arr = [];
for (var i = 0; i < times; i++) {
arr.push(thing);
}
return arr;
}
function indent(str, spaces) {
var lines = (str || '').split('\n');
var newArr = [];
for (var i = 0; i < lines.length; i++) {
newArr.push(repeat(' ', spaces).join('') + lines[i]);
}
return newArr.join('\n');
}
function specFailureDetails(result) {
printNewline();
print(result.fullName);
for (var i = 0; i < result.failedExpectations.length; i++) {
var failedExpectation = result.failedExpectations[i];
printNewline();
print(indent(failedExpectation.message, 2));
print(indent(failedExpectation.stack, 2));
}
printNewline();
}
function suiteFailureDetails(result) {
for (var i = 0; i < result.failedExpectations.length; i++) {
printNewline();
print(colored('red', 'An error was thrown in an afterAll'));
printNewline();
print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
}
printNewline();
}
}
return ConsoleReporter;
};

View File

@@ -5,11 +5,12 @@ var path = require('path'),
fs = require('fs');
var rootPath = path.join(__dirname, "jasmine-core"),
bootFiles = ['boot.js'],
bootFiles = ['boot0.js', 'boot1.js'],
legacyBootFiles = ['boot.js'],
nodeBootFiles = ['node_boot.js'],
cssFiles = [],
jsFiles = [],
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, nodeBootFiles);
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles, nodeBootFiles);
fs.readdirSync(rootPath).forEach(function(file) {
if(fs.statSync(path.join(rootPath, file)).isFile()) {

View File

@@ -1,3 +1,28 @@
if ENV["SUPPRESS_JASMINE_DEPRECATION"].nil?
puts <<~END_DEPRECATION_MSG
The Jasmine Ruby gems are deprecated. There will be no further releases after
the end of the Jasmine 3.x series. We recommend that most users migrate to the
jasmine-browser-runner npm package, which is the direct replacement for the
jasmine gem. See <https://jasmine.github.io/setup/browser.html> for setup
instructions, including for Rails applications that use either Sprockets or
Webpacker.
If jasmine-browser-runner doesn't meet your needs, one of these might:
* The jasmine npm package to run specs in Node.js:
<https://github.com/jasmine/jasmine-npm>
* The standalone distribution to run specs in browsers with no additional
tools: <https://github.com/jasmine/jasmine#installation>
* The jasmine-core npm package if all you need is the Jasmine assets:
<https://github.com/jasmine/jasmine>. This is the direct equivalent of the
jasmine-core Ruby gem.
To prevent this message from appearing, set the SUPPRESS_JASMINE_DEPRECATION
environment variable.
END_DEPRECATION_MSG
end
module Jasmine
module Core
class << self
@@ -6,7 +31,7 @@ module Jasmine
end
def js_files
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files - node_boot_files
(["jasmine.js"] + Dir.glob(File.join(path, "*.js"))).map { |f| File.basename(f) }.uniq - boot_files - ["boot0.js", "boot1.js"] - node_boot_files
end
SPEC_TYPES = ["core", "html", "node"]

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2021 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -21,6 +21,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
NOTE: This file is deprecated and will be removed in a future release.
Include both boot0.js and boot1.js (in that order) instead.
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
@@ -31,13 +35,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
(function() {
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire);
var jasmine = jasmineRequire.core(jasmineRequire),
global = jasmine.getGlobal();
global.jasmine = jasmine;
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
@@ -59,7 +66,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/**
* 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`.
*/
extend(window, jasmineInterface);
extend(global, jasmineInterface);
/**
* ## Runner Parameters
@@ -73,18 +80,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var filterSpecs = !!queryString.getParam("spec");
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
env.randomizeTests(random);
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -93,9 +103,7 @@ 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()); },
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -117,10 +125,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/

View File

@@ -1,4 +1,8 @@
/**
NOTE: This file is deprecated and will be removed in a future release.
Include both boot0.js and boot1.js (in that order) instead.
Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
@@ -9,13 +13,16 @@
*/
(function() {
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
window.jasmine = jasmineRequire.core(jasmineRequire);
var jasmine = jasmineRequire.core(jasmineRequire),
global = jasmine.getGlobal();
global.jasmine = jasmine;
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
@@ -37,7 +44,7 @@
/**
* 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`.
*/
extend(window, jasmineInterface);
extend(global, jasmineInterface);
/**
* ## Runner Parameters
@@ -51,18 +58,21 @@
var filterSpecs = !!queryString.getParam("spec");
var catchingExceptions = queryString.getParam("catch");
env.catchExceptions(typeof catchingExceptions === "undefined" ? true : catchingExceptions);
var throwingExpectationFailures = queryString.getParam("throwFailures");
env.throwOnExpectationFailure(throwingExpectationFailures);
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
env.randomizeTests(random);
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
env.seed(seed);
config.seed = seed;
}
/**
@@ -71,9 +81,7 @@
*/
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()); },
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
@@ -95,10 +103,12 @@
filterString: function() { return queryString.getParam("spec"); }
});
env.specFilter = function(spec) {
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/

View File

@@ -0,0 +1,42 @@
/**
This file starts the process of "booting" Jasmine. It initializes Jasmine,
makes its globals available, and creates the env. This file should be loaded
after `jasmine.js` and `jasmine_html.js`, but before `boot1.js` or any project
source files or spec files are loaded.
*/
(function() {
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
var jasmine = jasmineRequire.core(jasmineRequire),
global = jasmine.getGlobal();
global.jasmine = jasmine;
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = jasmineRequire.interface(jasmine, env);
/**
* 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`.
*/
for (var property in jasmineInterface) {
global[property] = jasmineInterface[property];
}
}());

View File

@@ -0,0 +1,111 @@
/**
This file finishes "booting" Jasmine, performing all of the necessary
initialization before executing the loaded environment and all of a project's
specs. This file should be loaded after `boot0.js` but before any project
source files or spec files are loaded. Thus this file can also be used to
customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can
be customized directly. If you only wish to configure the Jasmine env, you
can load another file that calls `jasmine.getEnv().configure({...})`
after `boot0.js` is loaded and before this file is loaded.
*/
(function() {
var env = jasmine.getEnv();
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
var filterSpecs = !!queryString.getParam("spec");
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
config.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).
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: new jasmine.Timer(),
filterSpecs: filterSpecs
});
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jsApiReporter);
env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
}
}());

View File

@@ -1,10 +1,7 @@
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../console/console.js');
consoleFns.console(consoleFns, jasmine);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

64
lib/jasmine-core/boot0.js Normal file
View File

@@ -0,0 +1,64 @@
/*
Copyright (c) 2008-2021 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
This file starts the process of "booting" Jasmine. It initializes Jasmine,
makes its globals available, and creates the env. This file should be loaded
after `jasmine.js` and `jasmine_html.js`, but before `boot1.js` or any project
source files or spec files are loaded.
*/
(function() {
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
/**
* ## Require &amp; Instantiate
*
* Require Jasmine's core files. Specifically, this requires and attaches all of Jasmine's code to the `jasmine` reference.
*/
var jasmine = jasmineRequire.core(jasmineRequire),
global = jasmine.getGlobal();
global.jasmine = jasmine;
/**
* Since this is being run in a browser and the results should populate to an HTML page, require the HTML-specific Jasmine code, injecting the same reference.
*/
jasmineRequire.html(jasmine);
/**
* Create the Jasmine environment. This is used to run all specs in a project.
*/
var env = jasmine.getEnv();
/**
* ## The Global Interface
*
* Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
*/
var jasmineInterface = jasmineRequire.interface(jasmine, env);
/**
* 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`.
*/
for (var property in jasmineInterface) {
global[property] = jasmineInterface[property];
}
}());

133
lib/jasmine-core/boot1.js Normal file
View File

@@ -0,0 +1,133 @@
/*
Copyright (c) 2008-2021 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
This file finishes "booting" Jasmine, performing all of the necessary
initialization before executing the loaded environment and all of a project's
specs. This file should be loaded after `boot0.js` but before any project
source files or spec files are loaded. Thus this file can also be used to
customize Jasmine for a project.
If a project is using Jasmine via the standalone distribution, this file can
be customized directly. If you only wish to configure the Jasmine env, you
can load another file that calls `jasmine.getEnv().configure({...})`
after `boot0.js` is loaded and before this file is loaded.
*/
(function() {
var env = jasmine.getEnv();
/**
* ## Runner Parameters
*
* More browser specific code - wrap the query string in an object and to allow for getting/setting parameters from the runner user interface.
*/
var queryString = new jasmine.QueryString({
getWindowLocation: function() { return window.location; }
});
var filterSpecs = !!queryString.getParam("spec");
var config = {
failFast: queryString.getParam("failFast"),
oneFailurePerSpec: queryString.getParam("oneFailurePerSpec"),
hideDisabled: queryString.getParam("hideDisabled")
};
var random = queryString.getParam("random");
if (random !== undefined && random !== "") {
config.random = random;
}
var seed = queryString.getParam("seed");
if (seed) {
config.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).
*/
var htmlReporter = new jasmine.HtmlReporter({
env: env,
navigateWithNewParam: function(key, value) { return queryString.navigateWithNewParam(key, value); },
addToExistingQueryString: function(key, value) { return queryString.fullStringWithNewParam(key, value); },
getContainer: function() { return document.body; },
createElement: function() { return document.createElement.apply(document, arguments); },
createTextNode: function() { return document.createTextNode.apply(document, arguments); },
timer: new jasmine.Timer(),
filterSpecs: filterSpecs
});
/**
* The `jsApiReporter` also receives spec results, and is used by any environment that needs to extract the results from JavaScript.
*/
env.addReporter(jsApiReporter);
env.addReporter(htmlReporter);
/**
* Filter which specs will be run by matching the start of the full name against the `spec` query param.
*/
var specFilter = new jasmine.HtmlSpecFilter({
filterString: function() { return queryString.getParam("spec"); }
});
config.specFilter = function(spec) {
return specFilter.matches(spec.getFullName());
};
env.configure(config);
/**
* Setting up timing functions to be able to be overridden. Certain browsers (Safari, IE 8, phantomjs) require this hack.
*/
window.setTimeout = window.setTimeout;
window.setInterval = window.setInterval;
window.clearTimeout = window.clearTimeout;
window.clearInterval = window.clearInterval;
/**
* ## Execution
*
* Replace the browser window's `onload`, ensure it's called, and then run all of the loaded specs. This includes initializing the `HtmlReporter` instance and then executing the loaded Jasmine environment. All of this will happen after all of the specs are loaded.
*/
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
htmlReporter.initialize();
env.execute();
};
/**
* Helper function for readability above.
*/
function extend(destination, source) {
for (var property in source) destination[property] = source[property];
return destination;
}
}());

View File

@@ -1,4 +1,33 @@
import pkg_resources
import os
if 'SUPPRESS_JASMINE_DEPRECATION' not in os.environ:
print('DEPRECATION WARNING:\n' +
'\n' +
'The Jasmine packages for Python are deprecated. There will be no further\n' +
'releases after the end of the Jasmine 3.x series. We recommend migrating to the\n' +
'following options:\n' +
'\n' +
'* jasmine-browser-runner (<https://github.com/jasmine/jasmine-browser>,\n' +
' `npm install jasmine-browser-runner`) to run specs in browsers, including\n' +
' headless Chrome and Saucelabs. This is the most direct replacement for the\n' +
' jasmine server` and `jasmine ci` commands provided by the `jasmine` Python\n' +
' package.\n' +
'* The jasmine npm package (<https://github.com/jasmine/jasmine-npm>,\n' +
' `npm install jasmine`) to run specs under Node.js.\n' +
'* The standalone distribution from the latest Jasmine release\n' +
' <https://github.com/jasmine/jasmine/releases> to run specs in browsers with\n' +
' no additional tools.\n' +
'* The jasmine-core npm package (`npm install jasmine-core`) if all you need is\n' +
' the Jasmine assets. This is the direct equivalent of the jasmine-core Python\n' +
' package.\n' +
'\n' +
'Except for the standalone distribution, all of the above are distributed through\n' +
'npm.\n' +
'\n' +
'To prevent this message from appearing, set the SUPPRESS_JASMINE_DEPRECATION\n' +
'environment variable.\n')
try:
from collections import OrderedDict
@@ -29,6 +58,11 @@ class Core(object):
js_files.remove('boot.js')
js_files.append('boot.js')
# Remove the new boot files. jasmine-py will continue to use the legacy
# boot.js.
js_files.remove('boot0.js')
js_files.remove('boot1.js')
return cls._uniq(js_files)
@classmethod
@@ -57,4 +91,4 @@ class Core(object):
seen[marker] = 1
result.append(item)
return result
return result

View File

@@ -19,4 +19,4 @@ Player.prototype.resume = function() {
Player.prototype.makeFavorite = function() {
this.currentlyPlayingSong.persistFavoriteStatus(true);
};
};

View File

@@ -4,4 +4,4 @@ function Song() {
Song.prototype.persistFavoriteStatus = function(value) {
// something complicated
throw new Error("not yet implemented");
};
};

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2021 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -20,6 +20,8 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
jasmineRequire.html = function(j$) {
j$.ResultsNode = jasmineRequire.ResultsNode();
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
@@ -28,12 +30,6 @@ jasmineRequire.html = function(j$) {
};
jasmineRequire.HtmlReporter = function(j$) {
var noopTimer = {
start: function() {},
elapsed: function() { return 0; }
};
function ResultsStateBuilder() {
this.topResults = new j$.ResultsNode({}, '', null);
this.currentParent = this.topResults;
@@ -48,18 +44,22 @@ jasmineRequire.HtmlReporter = function(j$) {
};
ResultsStateBuilder.prototype.suiteDone = function(result) {
this.currentParent.updateResult(result);
if (this.currentParent !== this.topResults) {
this.currentParent = this.currentParent.parent;
}
if (result.status === 'failed') {
this.failureCount++;
}
};
ResultsStateBuilder.prototype.specStarted = function(result) {
};
ResultsStateBuilder.prototype.specStarted = function(result) {};
ResultsStateBuilder.prototype.specDone = function(result) {
this.currentParent.addChild(result, 'spec');
if (result.status !== 'disabled') {
if (result.status !== 'excluded') {
this.specsExecuted++;
}
@@ -72,35 +72,42 @@ jasmineRequire.HtmlReporter = function(j$) {
}
};
function HtmlReporter(options) {
var env = options.env || {},
var config = function() {
return (options.env && options.env.configuration()) || {};
},
getContainer = options.getContainer,
createElement = options.createElement,
createTextNode = options.createTextNode,
onRaiseExceptionsClick = options.onRaiseExceptionsClick || function() {},
onThrowExpectationsClick = options.onThrowExpectationsClick || function() {},
onRandomClick = options.onRandomClick || function() {},
addToExistingQueryString = options.addToExistingQueryString || defaultQueryString,
navigateWithNewParam = options.navigateWithNewParam || function() {},
addToExistingQueryString =
options.addToExistingQueryString || defaultQueryString,
filterSpecs = options.filterSpecs,
timer = options.timer || noopTimer,
results = [],
htmlReporterMain,
symbols,
failedSuites = [];
deprecationWarnings = [];
this.initialize = function() {
clearPrior();
htmlReporterMain = createDom('div', {className: 'jasmine_html-reporter'},
createDom('div', {className: 'jasmine-banner'},
createDom('a', {className: 'jasmine-title', href: 'http://jasmine.github.io/', target: '_blank'}),
createDom('span', {className: 'jasmine-version'}, j$.version)
htmlReporterMain = createDom(
'div',
{ className: 'jasmine_html-reporter' },
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: 'jasmine-symbol-summary'}),
createDom('div', {className: 'jasmine-alert'}),
createDom('div', {className: 'jasmine-results'},
createDom('div', {className: 'jasmine-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);
@@ -109,10 +116,9 @@ jasmineRequire.HtmlReporter = function(j$) {
var totalSpecsDefined;
this.jasmineStarted = function(options) {
totalSpecsDefined = options.totalSpecsDefined || 0;
timer.start();
};
var summary = createDom('div', {className: 'jasmine-summary'});
var summary = createDom('div', { className: 'jasmine-summary' });
var stateBuilder = new ResultsStateBuilder();
@@ -121,11 +127,12 @@ jasmineRequire.HtmlReporter = function(j$) {
};
this.suiteDone = function(result) {
if (result.status == 'failed') {
failedSuites.push(result);
}
stateBuilder.suiteDone(result);
if (result.status === 'failed') {
failures.push(failureDom(result));
}
addDeprecationWarnings(result, 'suite');
};
this.specStarted = function(result) {
@@ -136,146 +143,196 @@ jasmineRequire.HtmlReporter = function(j$) {
this.specDone = function(result) {
stateBuilder.specDone(result);
if(noExpectations(result) && typeof console !== 'undefined' && typeof console.error !== 'undefined') {
console.error('Spec \'' + result.fullName + '\' has no expectations.');
if (noExpectations(result)) {
var noSpecMsg = "Spec '" + result.fullName + "' has no expectations.";
if (result.status === 'failed') {
console.error(noSpecMsg);
} else {
console.warn(noSpecMsg);
}
}
if (!symbols){
if (!symbols) {
symbols = find('.jasmine-symbol-summary');
}
symbols.appendChild(createDom('li', {
className: noExpectations(result) ? 'jasmine-empty' : 'jasmine-' + result.status,
symbols.appendChild(
createDom('li', {
className: this.displaySpecInCorrectFormat(result),
id: 'spec_' + result.id,
title: result.fullName
}
));
})
);
if (result.status == 'failed') {
var failure =
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: '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: 'jasmine-result-message'}, expectation.message));
messages.appendChild(createDom('div', {className: 'jasmine-stack-trace'}, expectation.stack));
}
failures.push(failure);
if (result.status === 'failed') {
failures.push(failureDom(result));
}
addDeprecationWarnings(result, 'spec');
};
this.displaySpecInCorrectFormat = function(result) {
return noExpectations(result) && result.status === 'passed'
? 'jasmine-empty'
: this.resultStatus(result.status);
};
this.resultStatus = function(status) {
if (status === 'excluded') {
return config().hideDisabled
? 'jasmine-excluded-no-display'
: 'jasmine-excluded';
}
return 'jasmine-' + status;
};
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 i;
alert.appendChild(
createDom(
'span',
{ className: 'jasmine-duration' },
'finished in ' + doneResult.totalTime / 1000 + 's'
)
);
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'))
)
));
var raiseCheckbox = find('#jasmine-raise-exceptions');
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';
}
};
banner.appendChild(optionsMenu(config()));
if (stateBuilder.specsExecuted < totalSpecsDefined) {
var skippedMessage = 'Ran ' + stateBuilder.specsExecuted + ' of ' + totalSpecsDefined + ' specs - run all';
var skippedLink = addToExistingQueryString('spec', '');
var skippedMessage =
'Ran ' +
stateBuilder.specsExecuted +
' of ' +
totalSpecsDefined +
' specs - run all';
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
var skippedLink =
(window.location.pathname || '') +
addToExistingQueryString('spec', '');
alert.appendChild(
createDom('span', {className: 'jasmine-bar jasmine-skipped'},
createDom('a', {href: skippedLink, title: 'Run all specs'}, skippedMessage)
createDom(
'span',
{ className: 'jasmine-bar jasmine-skipped' },
createDom(
'a',
{ href: skippedLink, title: 'Run all specs' },
skippedMessage
)
)
);
}
var statusBarMessage = '';
var statusBarClassName = 'jasmine-bar ';
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
var failed = stateBuilder.failureCount + globalFailures.length > 0;
if (totalSpecsDefined > 0) {
statusBarMessage += pluralize('spec', stateBuilder.specsExecuted) + ', ' + pluralize('failure', stateBuilder.failureCount);
if (stateBuilder.pendingSpecCount) { statusBarMessage += ', ' + pluralize('pending spec', stateBuilder.pendingSpecCount); }
statusBarClassName += (stateBuilder.failureCount > 0) ? 'jasmine-failed' : 'jasmine-passed';
if (totalSpecsDefined > 0 || failed) {
statusBarMessage +=
pluralize('spec', stateBuilder.specsExecuted) +
', ' +
pluralize('failure', stateBuilder.failureCount);
if (stateBuilder.pendingSpecCount) {
statusBarMessage +=
', ' + pluralize('pending spec', stateBuilder.pendingSpecCount);
}
}
if (doneResult.overallStatus === 'passed') {
statusBarClassName += ' jasmine-passed ';
} else if (doneResult.overallStatus === 'incomplete') {
statusBarClassName += ' jasmine-incomplete ';
statusBarMessage =
'Incomplete: ' +
doneResult.incompleteReason +
', ' +
statusBarMessage;
} else {
statusBarClassName += 'jasmine-skipped';
statusBarMessage += 'No specs found';
statusBarClassName += ' jasmine-failed ';
}
var seedBar;
if (order && order.random) {
seedBar = createDom('span', {className: 'jasmine-seed-bar'},
seedBar = createDom(
'span',
{ className: 'jasmine-seed-bar' },
', randomized with seed ',
createDom('a', {title: 'randomized with seed ' + order.seed, href: seedHref(order.seed)}, order.seed)
createDom(
'a',
{
title: 'randomized with seed ' + order.seed,
href: seedHref(order.seed)
},
order.seed
)
);
}
alert.appendChild(createDom('span', {className: statusBarClassName}, statusBarMessage, seedBar));
alert.appendChild(
createDom(
'span',
{ className: statusBarClassName },
statusBarMessage,
seedBar
)
);
var errorBarClassName = 'jasmine-bar jasmine-errored';
var errorBarMessagePrefix = 'AfterAll ';
var afterAllMessagePrefix = 'AfterAll ';
for(var i = 0; i < failedSuites.length; i++) {
var failedSuite = failedSuites[i];
for(var j = 0; j < failedSuite.failedExpectations.length; j++) {
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failedSuite.failedExpectations[j].message));
for (i = 0; i < globalFailures.length; i++) {
alert.appendChild(
createDom(
'span',
{ className: errorBarClassName },
globalFailureMessage(globalFailures[i])
)
);
}
function globalFailureMessage(failure) {
if (failure.globalErrorType === 'load') {
var prefix = 'Error during loading: ' + failure.message;
if (failure.filename) {
return (
prefix + ' in ' + failure.filename + ' line ' + failure.lineno
);
} else {
return prefix;
}
} else {
return afterAllMessagePrefix + failure.message;
}
}
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
for(i = 0; i < globalFailures.length; i++) {
var failure = globalFailures[i];
alert.appendChild(createDom('span', {className: errorBarClassName}, errorBarMessagePrefix + failure.message));
addDeprecationWarnings(doneResult);
for (i = 0; i < deprecationWarnings.length; i++) {
var context;
switch (deprecationWarnings[i].runnableType) {
case 'spec':
context = '(in spec: ' + deprecationWarnings[i].runnableName + ')';
break;
case 'suite':
context = '(in suite: ' + deprecationWarnings[i].runnableName + ')';
break;
default:
context = '';
}
alert.appendChild(
createDom(
'span',
{ className: 'jasmine-bar jasmine-warning' },
'DEPRECATION: ' + deprecationWarnings[i].message,
createDom('br'),
context
)
);
}
var results = find('.jasmine-results');
@@ -283,62 +340,39 @@ jasmineRequire.HtmlReporter = function(j$) {
summaryList(stateBuilder.topResults, summary);
function summaryList(resultsTree, domParent) {
var specListNode;
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (filterSpecs && !hasActiveSpec(resultNode)) {
continue;
}
if (resultNode.type == 'suite') {
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)
)
);
summaryList(resultNode, suiteListNode);
domParent.appendChild(suiteListNode);
}
if (resultNode.type == 'spec') {
if (domParent.getAttribute('class') != 'jasmine-specs') {
specListNode = createDom('ul', {className: 'jasmine-specs'});
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
if(noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if(resultNode.result.status === 'pending' && resultNode.result.pendingReason !== '') {
specDescription = specDescription + ' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom('li', {
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom('a', {href: specHref(resultNode.result)}, specDescription)
)
);
}
}
}
if (failures.length) {
alert.appendChild(
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-spec-list'},
createDom(
'span',
{ className: 'jasmine-menu jasmine-bar jasmine-spec-list' },
createDom('span', {}, 'Spec List | '),
createDom('a', {className: 'jasmine-failures-menu', href: '#'}, 'Failures')));
createDom(
'a',
{ className: 'jasmine-failures-menu', href: '#' },
'Failures'
)
)
);
alert.appendChild(
createDom('span', {className: 'jasmine-menu jasmine-bar jasmine-failure-list'},
createDom('a', {className: 'jasmine-spec-list-menu', href: '#'}, 'Spec List'),
createDom('span', {}, ' | Failures ')));
createDom(
'span',
{ className: 'jasmine-menu jasmine-bar jasmine-failure-list' },
createDom(
'a',
{ className: 'jasmine-spec-list-menu', href: '#' },
'Spec List'
),
createDom('span', {}, ' | Failures ')
)
);
find('.jasmine-failures-menu').onclick = function() {
setMenuModeTo('jasmine-failure-list');
return false;
};
find('.jasmine-spec-list-menu').onclick = function() {
setMenuModeTo('jasmine-spec-list');
return false;
};
setMenuModeTo('jasmine-failure-list');
@@ -352,6 +386,283 @@ jasmineRequire.HtmlReporter = function(j$) {
return this;
function failureDom(result) {
var failure = createDom(
'div',
{ className: 'jasmine-spec-detail jasmine-failed' },
failureDescription(result, stateBuilder.currentParent),
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: 'jasmine-result-message' },
expectation.message
)
);
messages.appendChild(
createDom(
'div',
{ className: 'jasmine-stack-trace' },
expectation.stack
)
);
}
if (result.failedExpectations.length === 0) {
messages.appendChild(
createDom(
'div',
{ className: 'jasmine-result-message' },
'Spec has no expectations'
)
);
}
return failure;
}
function summaryList(resultsTree, domParent) {
var specListNode;
for (var i = 0; i < resultsTree.children.length; i++) {
var resultNode = resultsTree.children[i];
if (filterSpecs && !hasActiveSpec(resultNode)) {
continue;
}
if (resultNode.type === 'suite') {
var suiteListNode = createDom(
'ul',
{ className: 'jasmine-suite', id: 'suite-' + resultNode.result.id },
createDom(
'li',
{
className:
'jasmine-suite-detail jasmine-' + resultNode.result.status
},
createDom(
'a',
{ href: specHref(resultNode.result) },
resultNode.result.description
)
)
);
summaryList(resultNode, suiteListNode);
domParent.appendChild(suiteListNode);
}
if (resultNode.type === 'spec') {
if (domParent.getAttribute('class') !== 'jasmine-specs') {
specListNode = createDom('ul', { className: 'jasmine-specs' });
domParent.appendChild(specListNode);
}
var specDescription = resultNode.result.description;
if (noExpectations(resultNode.result)) {
specDescription = 'SPEC HAS NO EXPECTATIONS ' + specDescription;
}
if (
resultNode.result.status === 'pending' &&
resultNode.result.pendingReason !== ''
) {
specDescription =
specDescription +
' PENDING WITH MESSAGE: ' +
resultNode.result.pendingReason;
}
specListNode.appendChild(
createDom(
'li',
{
className: 'jasmine-' + resultNode.result.status,
id: 'spec-' + resultNode.result.id
},
createDom(
'a',
{ href: specHref(resultNode.result) },
specDescription
)
)
);
}
}
}
function optionsMenu(config) {
var optionsMenuDom = createDom(
'div',
{ className: 'jasmine-run-options' },
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
createDom(
'div',
{ className: 'jasmine-payload' },
createDom(
'div',
{ className: 'jasmine-stop-on-failure' },
createDom('input', {
className: 'jasmine-fail-fast',
id: 'jasmine-fail-fast',
type: 'checkbox'
}),
createDom(
'label',
{ className: 'jasmine-label', for: 'jasmine-fail-fast' },
'stop execution on spec failure'
)
),
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'
)
),
createDom(
'div',
{ className: 'jasmine-hide-disabled' },
createDom('input', {
className: 'jasmine-disabled',
id: 'jasmine-hide-disabled',
type: 'checkbox'
}),
createDom(
'label',
{ className: 'jasmine-label', for: 'jasmine-hide-disabled' },
'hide disabled tests'
)
)
)
);
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
failFastCheckbox.checked = config.stopOnSpecFailure;
failFastCheckbox.onclick = function() {
navigateWithNewParam('failFast', !config.stopOnSpecFailure);
};
var throwCheckbox = optionsMenuDom.querySelector(
'#jasmine-throw-failures'
);
throwCheckbox.checked = config.stopSpecOnExpectationFailure;
throwCheckbox.onclick = function() {
navigateWithNewParam(
'oneFailurePerSpec',
!config.stopSpecOnExpectationFailure
);
};
var randomCheckbox = optionsMenuDom.querySelector(
'#jasmine-random-order'
);
randomCheckbox.checked = config.random;
randomCheckbox.onclick = function() {
navigateWithNewParam('random', !config.random);
};
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
hideDisabled.checked = config.hideDisabled;
hideDisabled.onclick = function() {
navigateWithNewParam('hideDisabled', !config.hideDisabled);
};
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
optionsPayload = optionsMenuDom.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';
}
};
return optionsMenuDom;
}
function failureDescription(result, suite) {
var wrapper = createDom(
'div',
{ className: 'jasmine-description' },
createDom(
'a',
{ title: result.description, href: specHref(result) },
result.description
)
);
var suiteLink;
while (suite && suite.parent) {
wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild);
suiteLink = createDom(
'a',
{ href: suiteHref(suite) },
suite.result.description
);
wrapper.insertBefore(suiteLink, wrapper.firstChild);
suite = suite.parent;
}
return wrapper;
}
function suiteHref(suite) {
var els = [];
while (suite && suite.parent) {
els.unshift(suite.result.description);
suite = suite.parent;
}
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
return (
(window.location.pathname || '') +
addToExistingQueryString('spec', els.join(' '))
);
}
function addDeprecationWarnings(result, runnableType) {
if (result && result.deprecationWarnings) {
for (var i = 0; i < result.deprecationWarnings.length; i++) {
var warning = result.deprecationWarnings[i].message;
if (!j$.util.arrayContains(warning)) {
deprecationWarnings.push({
message: warning,
runnableName: result.fullName,
runnableType: runnableType
});
}
}
}
}
function find(selector) {
return getContainer().querySelector('.jasmine_html-reporter ' + selector);
}
@@ -360,7 +671,7 @@ jasmineRequire.HtmlReporter = function(j$) {
// return the reporter
var oldReporter = find('');
if(oldReporter) {
if (oldReporter) {
getContainer().removeChild(oldReporter);
}
}
@@ -392,17 +703,25 @@ jasmineRequire.HtmlReporter = function(j$) {
}
function pluralize(singular, count) {
var word = (count == 1 ? singular : singular + 's');
var word = count == 1 ? singular : singular + 's';
return '' + count + ' ' + word;
}
function specHref(result) {
return addToExistingQueryString('spec', result.fullName);
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
return (
(window.location.pathname || '') +
addToExistingQueryString('spec', result.fullName)
);
}
function seedHref(seed) {
return addToExistingQueryString('seed', seed);
// include window.location.pathname to fix issue with karma-jasmine-html-reporter in angular: see https://github.com/jasmine/jasmine/issues/1906
return (
(window.location.pathname || '') +
addToExistingQueryString('seed', seed)
);
}
function defaultQueryString(key, value) {
@@ -414,12 +733,17 @@ jasmineRequire.HtmlReporter = function(j$) {
}
function noExpectations(result) {
return (result.failedExpectations.length + result.passedExpectations.length) === 0 &&
result.status === 'passed';
var allExpectations =
result.failedExpectations.length + result.passedExpectations.length;
return (
allExpectations === 0 &&
(result.status === 'passed' || result.status === 'failed')
);
}
function hasActiveSpec(resultNode) {
if (resultNode.type == 'spec' && resultNode.result.status != 'disabled') {
if (resultNode.type == 'spec' && resultNode.result.status != 'excluded') {
return true;
}
@@ -438,7 +762,10 @@ jasmineRequire.HtmlReporter = function(j$) {
jasmineRequire.HtmlSpecFilter = function() {
function HtmlSpecFilter(options) {
var filterString = options && options.filterString() && options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
var filterString =
options &&
options.filterString() &&
options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
var filterPattern = new RegExp(filterString);
this.matches = function(specName) {
@@ -464,6 +791,10 @@ jasmineRequire.ResultsNode = function() {
this.last = function() {
return this.children[this.children.length - 1];
};
this.updateResult = function(result) {
this.result = result;
};
}
return ResultsNode;
@@ -471,9 +802,11 @@ jasmineRequire.ResultsNode = function() {
jasmineRequire.QueryString = function() {
function QueryString(options) {
this.navigateWithNewParam = function(key, value) {
options.getWindowLocation().search = this.fullStringWithNewParam(key, value);
options.getWindowLocation().search = this.fullStringWithNewParam(
key,
value
);
};
this.fullStringWithNewParam = function(key, value) {
@@ -491,7 +824,9 @@ jasmineRequire.QueryString = function() {
function toQueryString(paramMap) {
var qStrPairs = [];
for (var prop in paramMap) {
qStrPairs.push(encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop]));
qStrPairs.push(
encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])
);
}
return '?' + qStrPairs.join('&');
}
@@ -515,7 +850,6 @@ jasmineRequire.QueryString = function() {
return paramMap;
}
}
return QueryString;

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Pivotal Labs
Copyright (c) 2008-2021 Pivotal Labs
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -23,10 +23,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
module.exports = function(jasmineRequire) {
var jasmine = jasmineRequire.core(jasmineRequire);
var consoleFns = require('../console/console.js');
consoleFns.console(consoleFns, jasmine);
var env = jasmine.getEnv();
var env = jasmine.getEnv({suppressLoadErrors: true});
var jasmineInterface = jasmineRequire.interface(jasmine, env);

View File

@@ -1 +0,0 @@
../../spec

View File

@@ -4,6 +4,6 @@
#
module Jasmine
module Core
VERSION = "2.9.1"
VERSION = "3.10.1"
end
end

View File

@@ -1,34 +1,104 @@
{
"name": "jasmine-core",
"license": "MIT",
"version": "2.9.1",
"version": "3.10.1",
"repository": {
"type": "git",
"url": "https://github.com/jasmine/jasmine.git"
},
"keywords": [
"test",
"testing",
"jasmine",
"tdd",
"bdd"
],
"scripts": {
"test": "grunt jshint execSpecsInNode"
"posttest": "eslint \"src/**/*.js\" \"spec/**/*.js\" && prettier --check \"src/**/*.js\" \"spec/**/*.js\"",
"test": "grunt --stack execSpecsInNode",
"cleanup": "prettier --write \"src/**/*.js\" \"spec/**/*.js\"",
"build": "grunt buildDistribution",
"serve": "node spec/support/localJasmineBrowser.js",
"serve:performance": "node spec/support/localJasmineBrowser.js jasmine-browser-performance.json",
"ci": "node spec/support/ci.js",
"ci:performance": "node spec/support/ci.js jasmine-browser-performance.json"
},
"description": "Official packaging of Jasmine's core files for use by Node.js projects.",
"homepage": "http://jasmine.github.io",
"description": "Simple JavaScript testing framework for browsers and node.js",
"homepage": "https://jasmine.github.io",
"main": "./lib/jasmine-core.js",
"files": [
"MIT.LICENSE",
"README.md",
"images/*.{png,svg}",
"lib/**/*.{js,css}",
"package.json"
],
"devDependencies": {
"glob": "~7.1.2",
"grunt": "^1.0.1",
"grunt-cli": "^1.2.0",
"grunt-contrib-compass": "^1.1.1",
"ejs": "^2.5.5",
"eslint": "^6.8.0",
"eslint-plugin-compat": "^3.8.0",
"fast-glob": "^2.2.6",
"grunt": "^1.0.4",
"grunt-cli": "^1.3.2",
"grunt-contrib-compress": "^1.3.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-jshint": "^1.0.0",
"jasmine": "^2.5.0",
"load-grunt-tasks": "^0.4.0",
"shelljs": "^0.7.0",
"temp": "~0.8.1"
}
"grunt-css-url-embed": "^1.11.1",
"grunt-sass": "^3.0.2",
"jasmine": "^3.4.0",
"jasmine-browser-runner": "github:jasmine/jasmine-browser#main",
"jsdom": "^15.0.0",
"load-grunt-tasks": "^4.0.0",
"prettier": "1.17.1",
"sass": "^1.32.12",
"shelljs": "^0.8.3",
"temp": "^0.9.0"
},
"prettier": {
"singleQuote": true
},
"eslintConfig": {
"extends": [
"plugin:compat/recommended"
],
"parserOptions": {
"ecmaVersion": 5
},
"rules": {
"quotes": [
"error",
"single",
{
"avoidEscape": true
}
],
"no-unused-vars": [
"error",
{
"args": "none"
}
],
"block-spacing": "error",
"func-call-spacing": [
"error",
"never"
],
"key-spacing": "error",
"no-tabs": "error",
"no-trailing-spaces": "error",
"no-whitespace-before-property": "error",
"semi": [
"error",
"always"
],
"space-before-blocks": "error"
}
},
"browserslist": [
"Safari >= 8",
"last 2 Chrome versions",
"last 2 Firefox versions",
"Firefox 68",
"last 2 Edge versions",
"IE >= 10"
]
}

19
release_notes/2.99.md Normal file
View File

@@ -0,0 +1,19 @@
# Jasmine-Core 2.99 Release Notes
## Summary
This release is part of the upgrade path to Jasmine 3.0. It deprecates some functionality that will change.
## Changes
* Add ability to report deprecation warnings from within the suite and display them in the HTML reporter
* Add deprecation messages for things that will change/break in 3.0
* * done for async functionality will now add a failure if it is invoked with an Error
* * Env.catchExceptions and the query param are going away, in favor of a more fully functional fail fast handler
* * jasmine.Any(Object) will no longer match null
* * Unhandled errors during suite load will be caught and reported as failures by Jasmine
* * Calling execute more than once on the same spec will definitely fail in 3.0
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

91
release_notes/3.0.md Normal file
View File

@@ -0,0 +1,91 @@
# Jasmine-Core 3.0 Release Notes
## Summary
Jasmine 3.0 is a major release of Jasmine, and as such includes some breaking changes in addition to various new features.
There is also a 2.99 release of Jasmine that will present deprecation warnings for suites that will encounter different behavior in 3.0.
## Breaking Changes
* Replace old "catch exceptions" logic with proper fail fast with error reporting
- Fixes [#414](https://github.com/jasmine/jasmine/issues/414)
- Fixes [jasmine/jasmine-npm#16](https://github.com/jasmine/jasmine-npm/issues/16)
* Detect an Error passed to `done` and add an expectation failure
- Fixes [#567](https://github.com/jasmine/jasmine/issues/567)
* Unify status for xdescribe and xit
- Ensure *All's only execute if at least one child will run
- Specs will report a status of `excluded` instead of disabled
- Fixes [#1418](https://github.com/jasmine/jasmine/issues/1418)
* Suite level errors all report the same way (on suiteDone)
* Refactor QueueRunner and remove references to functions that Jasmine is done with
* expect(null).toEqual(jasmine.any(Object)) no longer passes
- Fixes [#1255](https://github.com/jasmine/jasmine/issues/1255)
* Default to running tests in random order
* The `identity` of a Jasmnine Spy is now a property and no longer a method
* Additionally, Jasmine 3.0 drops support for older browsers and environments. Notably:
- Internet Explorer 8 and 9
- Ruby 1.x (for the Ruby gem)
- Rails 3.x (for the Ruby gem)
- Python 2.x (for the Python wheel)
- Nodejs 0.x (for the NPM package)
## Changes
* Remove node modules from python wheel, and update languages
* Allow reporter callbacks to be asynchronous
- Fixes [#842](https://github.com/jasmine/jasmine/issues/842)
* Allow adding custom spy strategies
* Add the ability to specify the strategy to use for a spy based on which parameters are passed
* Added links to re-run the suites containing a failing spec
* Added a toHaveClass matcher
* More informative pretty-printing of DOM elements
* Allow jasmine-npm to handle its own load errors
* Treat random= as a no-op rather than disabling randomization
* Use prototype for spy strategy for better memory management
* Remove console.js altogether
* Add safari 10 and update readme to include edge
* Determine overall status in core, not reporters
* Filter Jasmine frames from stack traces
* Treat afterAll errors at any level as failures
* Improved reporting of load errors and afterAll errors
- Pass file and line number to reporters when present
- Show file and line number in the HTML reporter when present
- Visually separate adjacent errors in the HTML reporter
* Report loading errors as loading errors, not afterAll errors
* HTML reporter reports overall failure if there are any global errors
* Fail if error events (e.g. syntax errors) occur during loading
* Allow use of a predicate function to validate thrown exceptions
* Check truthiness of toThrowError args, not arg count
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

54
release_notes/3.1.0.md Normal file
View File

@@ -0,0 +1,54 @@
# Jasmine-Core 3.1 Release Notes
## Summary
This release contains a number of fixes and pull requests
## Pull Requests and Issues
* Display error properties for failed specs
- Merges [#1516](https://github.com/jasmine/jasmine/issues/1516) from @jbunton-atlassian
* Allow node to report load time errors
- Fixes [#1519](https://github.com/jasmine/jasmine/issues/1519)
* Fixing missing semi-colons
- Merges [#1512](https://github.com/jasmine/jasmine/issues/1512) from @Sylhare
* Fixed release notes link
* Added matchers: truthy, falsy, empty and notEmpty
- Merges [#1460](https://github.com/jasmine/jasmine/issues/1460) from @sjolicoeur
* Add API docs for async reporters
* Return <anonymous> for functions that have no actual words between keyword and (
- Also fixes a potential catastrophic backtracking if someone has
severely damaged their own `toString` during test execution.
* Moved toHaveClass matcher into core so that it can be used in Karma
- Fixes [#1503](https://github.com/jasmine/jasmine/issues/1503)
* allow adding a deprecation object
- Merges [#1498](https://github.com/jasmine/jasmine/issues/1498) from @UziTech
* Add CodeTriage badge to jasmine/jasmine
- Merges [#1505](https://github.com/jasmine/jasmine/issues/1505) from @codetriage-readme-bot
* Resolve merge conflict
- Merges [#1501](https://github.com/jasmine/jasmine/issues/1501) from @aptx4869
- Fixes [#1500](https://github.com/jasmine/jasmine/issues/1500)
* Fix release note typo
- Merges [#1499](https://github.com/jasmine/jasmine/issues/1499) @bcaudan
* Only show deprecation for catch exceptions if you tell Jasmine not to catch
- Fixes [#1497](https://github.com/jasmine/jasmine/issues/1497)
* Add notes for environments that have lost support
- Fixes [#1495](https://github.com/jasmine/jasmine/issues/1495)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

57
release_notes/3.10.0.md Normal file
View File

@@ -0,0 +1,57 @@
# Jasmine Core 3.10 Release Notes
## New features and bug fixes
* Added support for running Jasmine multiple times
* If the env is configured with `autoCleanClosures: false`, then it can be
executed repeatedly.
* Merges #1934 from @nicojs
* Fixes #1925
* Improved error message when an async expectation occurs after the spec
finishes
* Merges #1937 from @AndreWillomitzer
* Fixes #1854
* Reject timeout values that are too large for setTimeout
* See #1930
* Don't immediately move to the next queueable fn on async error
This allows assertion failures and other errors that occur after the async
error to be routed to the correct spec/suite.
* Added a stringContaining asymmetric equality tester
* Fixes #1923.
* The jasmine-core Ruby gem now prints a deprecation message when loaded unless
the SUPPRESS_JASMINE_DEPRECATION environment variable is set.
## Documentation updates
* Added discussion of max timeout value to jsdocs
* Merges #1931 from @trusktr
* Added missing @since annotations
* Improved jsdocs for asymmetric equality testers
* Added a deprecation notice to the jasmine-core Ruby gem's description
## Supported environments
jasmine-core 3.10.0 has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------|
| Node | 10, 12, 14, 16 |
| Safari | 8-14 |
| Chrome | 94 |
| Firefox | 93, 78, 68 |
| Edge | 94 |
| Internet Explorer | 10, 11 |
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

12
release_notes/3.10.1.md Normal file
View File

@@ -0,0 +1,12 @@
# Jasmine Core 3.10.1 Release Notes
## Bugfixes
* Fixed missing pendingReason in pending spec results
* Fixes [#1939](https://github.com/jasmine/jasmine/issues/1939)
* Merges [#1940](https://github.com/jasmine/jasmine/pull/1940) from @jan-molak
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

83
release_notes/3.2.0.md Normal file
View File

@@ -0,0 +1,83 @@
# Jasmine-Core 3.2 Release Notes
## Summary
This release contains a number of fixes and pull requests
## Changes
* Add spyOnAllFunctions function
- Merges [#1581](https://github.com/jasmine/jasmine/issues/1581) from @aeisenberg
- Fixes [#1421](https://github.com/jasmine/jasmine/issues/1421)
* Improve timeout error message
- Merges [#1567](https://github.com/jasmine/jasmine/issues/1567) from @ikonst
* Fix JSDoc naming for Env functions
- See [#1565](https://github.com/jasmine/jasmine/issues/1565)
* Add documentation for more public functions on Env
- Fixes [#1565](https://github.com/jasmine/jasmine/issues/1565)
* Added a basic set of async matchers
- Fixes [#1447](https://github.com/jasmine/jasmine/issues/1447)
- Fixes [#1547](https://github.com/jasmine/jasmine/issues/1547)
* Properly cascade StopExecutionError's up the tree
- Fixes [#1563](https://github.com/jasmine/jasmine/issues/1563)
* Implemented hiding of disabled specs
- Merges [#1561](https://github.com/jasmine/jasmine/issues/1561) from @SamFare
* Line-break long expectation failure messages
- See [#296](https://github.com/jasmine/jasmine/issues/296)
* Better detection of DOM Nodes for equality
- Fixes [#1172](https://github.com/jasmine/jasmine/issues/1172)
* Fix typo from `incimplete` to `incomplete`
- Merges [#1555](https://github.com/jasmine/jasmine/issues/1555) from @yinm
* Allow omitting the name argument: `createSpy(func)`
- Merges [#1551](https://github.com/jasmine/jasmine/issues/1551) from @riophae
* name new global status stuff correctly in API docs
* Check for accidental global variable creation
* Fixed global variable leak
- Fixes [#1534](https://github.com/jasmine/jasmine/issues/1534)
* Correctly format stack traces for errors with multiline messages
- Fixes [#1526](https://github.com/jasmine/jasmine/issues/1526)
* Change message for extra elements at end of actual array
- Merges [#1527](https://github.com/jasmine/jasmine/issues/1527) from @majidmade
- Fixes [#1485](https://github.com/jasmine/jasmine/issues/1485)
* Report unhandled rejections as globalErrors.
- Merges [#1521](https://github.com/jasmine/jasmine/issues/1521) from @johnjbarton
* add some links to more tutorials from the api docs
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

11
release_notes/3.2.1.md Normal file
View File

@@ -0,0 +1,11 @@
# Jasmine-Core 3.2.1 Release Notes
## Changes
* Correctly expose `spyOnAllFunctions`
- See [#1581](https://github.com/jasmine/jasmine/issues/1581)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

47
release_notes/3.3.0.md Normal file
View File

@@ -0,0 +1,47 @@
# Jasmine Core 3.3 Release Notes
## Summary
This release includes a new way to configure Jasmine, the ability to provide additional
context with your expectations, and other things
## Changes
* Added expect().withContext() to provide additional information in failure messages
* Implement `withContext` for async expectations too
- Fixes [#641](https://github.com/jasmine/jasmine/issues/641)
* New asynchronous matcher `toBeRejectedWith`
- Merges [#1615](https://github.com/jasmine/jasmine/issues/1615) from @codymikol
- Closes [#1600](https://github.com/jasmine/jasmine/issues/1600)
- Fixes [#1595](https://github.com/jasmine/jasmine/issues/1595)
* Show a tip for `toBe` failures for how to get deep equality
- Merges [#1616](https://github.com/jasmine/jasmine/issues/1616) from @tdurtshi
- Fixes [#1614](https://github.com/jasmine/jasmine/issues/1614)
* `expectAsync` now works with non-native promises
- Merges [#1613](https://github.com/jasmine/jasmine/issues/1613) from @codymikol
- Fixes [#1612](https://github.com/jasmine/jasmine/issues/1612)
* Show status marks next to spec description in HTML reporter
- Merges [#1610](https://github.com/jasmine/jasmine/issues/1610) from @m1010j
- Fixes [#1596](https://github.com/jasmine/jasmine/issues/1596)
* Show error messages for `Error`s without a name
- Merges [#1601](https://github.com/jasmine/jasmine/issues/1601) from @nitobuendia
- Fixes [#1594](https://github.com/jasmine/jasmine/issues/1594)
* Optimized clearTimeout cpu usage
- Merges [#1599](https://github.com/jasmine/jasmine/issues/1599) from @Havunen
* Introduce a configuration object to `Env` deprecating old single use functions
- [finishes #159158038](http://www.pivotaltracker.com/story/159158038)
* Specify https for github urls in package.json
- Merges [#1597](https://github.com/jasmine/jasmine/issues/1597) @limonte
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

49
release_notes/3.4.0.md Normal file
View File

@@ -0,0 +1,49 @@
# Jasmine Core 3.4 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes
## Changes
* Handle WebSocket events in IE when detecting Errors
- Fixes [#1623](https://github.com/jasmine/jasmine/issues/1623)
* bump dependencies for security fixes
- Merges [#1672](https://github.com/jasmine/jasmine/issues/1672) from @wood1986
* Make node execution default and override for browsers
- Merges [#1658](https://github.com/jasmine/jasmine/issues/1658) from @wood1986
- Fixes [#883](https://github.com/jasmine/jasmine/issues/883)
* feat(result.duration): report test duration in ms
- Merges [#1660](https://github.com/jasmine/jasmine/issues/1660) from @johnjbarton
- Fixes [#1646](https://github.com/jasmine/jasmine/issues/1646)
* refactor(Timer): share htmlReporter noopTimer via Timer.js
- Merges [#1669](https://github.com/jasmine/jasmine/issues/1669) from @johnjbarton
* Fix various typos
- Merges [#1666](https://github.com/jasmine/jasmine/issues/1666) from @FelixRilling
- Merges [#1667](https://github.com/jasmine/jasmine/issues/1667) from @FelixRilling
- Merges [#1665](https://github.com/jasmine/jasmine/issues/1665) from @FelixRilling
- Merges [#1664](https://github.com/jasmine/jasmine/issues/1664) from @FelixRilling
- Fixes [#1663](https://github.com/jasmine/jasmine/issues/1663)
* When catching a global error in Node.js, print the type of error
- Merges [#1632](https://github.com/jasmine/jasmine/issues/1632) from @jbunton-atlassian
* Support Error.stack in globalErrors.
- Merges [#1644](https://github.com/jasmine/jasmine/issues/1644) from @johnjbarton
* Stop treating objects with a `nodeType` as if they are DOM Nodes
- Fixes [#1638](https://github.com/jasmine/jasmine/issues/1638)
* Fixes issue where PhantomJS 2 and IE 10 - 11 crashed when reporting SVG element equality
- Merges [#1621](https://github.com/jasmine/jasmine/issues/1621) from @Havunen
- Fixes [#1618](https://github.com/jasmine/jasmine/issues/1618)
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

199
release_notes/3.5.0.md Normal file
View File

@@ -0,0 +1,199 @@
# Jasmine Core 3.5 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes
### Highlights
* The output of toHaveBeenCalledWith should now be more readable
This breaks each call out onto its own line, so that it's much easier to
see where each call starts and how they differ. E.g. previously the output
would be:
Expected spy foo to have been called with [ 'bar', 'baz', 'qux' ] but actual calls were [ [ 42, 'wibble' ], [ 'bar' 'qux' ], [ 'grault '] ]
Now it's:
Expected spy foo to have been called with:
[ 'bar', 'baz', 'qux' ]
but actual calls were:
[ 42, 'wibble' ],
[ 'bar' 'qux' ],
[ 'grault '].
* Add new spy strategies to resolve and reject Promises `resolveTo` and `rejectWith`
* Add the ability to have custom async matchers
### Internal notes
* Stop testing against PhantomJS
* PhantomJS is at end of life, and the last version of Selenium that supported it was 3.6.0, released almost three years ago. We can't test Jasmine against PhantomJS without pinning key pieces of the project to increasingly outdated versions of key libraries.
* Fail Jasmine's CI build if the promise returned from `jasmineBrowser.runSpecs` is rejected
* A bunch of other rejiggering of the Travis-CI builds to make them easier to work with
* Also released a new browser runner that is being used by Jasmine
* See [jasmine-browser-runner](https://github.com/jasmine/jasmine-browser)
* This is a first pass at getting this to work for other projects as well. Please try it out and let us know what isn't working for you.
* add prettier and eslint
## All Changes
* Adds new configuration option to failSpecWithNoExpectations that will report specs without expectations as failures if enabled
* Merges [#1743](https://github.com/jasmine/jasmine/issues/1743) from @dtychshenko
* Fixes [#1740](https://github.com/jasmine/jasmine/issues/1740)
* Correctly propagate the `Error` object caught by the global error handler to reporters, etc.
- Merges [#1738](https://github.com/jasmine/jasmine/issues/1738) from @prantlf
- Fixes [#1728](https://github.com/jasmine/jasmine/issues/1728)
* Show argument diffs in toHaveBeenCalledWith failure messages
* Fixes [#1641](https://github.com/jasmine/jasmine/issues/1641)
* Updated arrayContaining to require actual values to be arrays
* Merges [#1746](https://github.com/jasmine/jasmine/issues/1746) from @divido
* Fixes [#1745](https://github.com/jasmine/jasmine/issues/1745)
* Add the ability to have custom async matchers
* Merges [#1732](https://github.com/jasmine/jasmine/issues/1732) from @UziTech
* Allow users to set a default spy strategy
- Merges [#1716](https://github.com/jasmine/jasmine/issues/1716) from @elliot-nelson
* Accept configurations with `Promise: undefined`.
* PrettyPrinter survives if objects throw in toString
- Merges [#1718](https://github.com/jasmine/jasmine/issues/1718) from @johnjbarton
- Fixes [#1726](https://github.com/jasmine/jasmine/issues/1726)
* Add `mapContaining` and `setContaining` asymmetric matchers
* Merges [#1741](https://github.com/jasmine/jasmine/issues/1741) from @eventlistener
* Use the same spec file pattern for both node and browser
* Gemspec: Drop EOL'd property rubyforge_project
* Merges [#1736](https://github.com/jasmine/jasmine/issues/1736) from @olleolleolle
* Updated async timeout message to include all of the ways that async code can be run in Jasmine
* Allow users to pass property names to createSpyObj
- Merges [#1722](https://github.com/jasmine/jasmine/issues/1722) from @elliot-nelson
- Closes [#1569](https://github.com/jasmine/jasmine/issues/1569)
- Fixes [#1442](https://github.com/jasmine/jasmine/issues/1442)
* don't attempt to normalize PNGs (gitattributes)
- Merges [#1721](https://github.com/jasmine/jasmine/issues/1721) from @elliot-nelson
* Add `@since` to most JSDoc comments
- See [jasmine/jasmine.github.io#117](https://github.com/jasmine/jasmine.github.io/issues/117)
* Make no expectations in HTML Reporter message a console warning
- Fixes [#1704](https://github.com/jasmine/jasmine/issues/1704)
* Prevent page overflow in HTML reporter under some situations by setting an explicit width
- Merges [#1713](https://github.com/jasmine/jasmine/issues/1713) from @pixelpax
* Cleanup: minor dead code removal and style fixes
- Merges [#1708](https://github.com/jasmine/jasmine/issues/1708) from @elliot-nelson
* Pretty Printer can now handle printing an object whose `toString` function has been spied upon
- Merges [#1712](https://github.com/jasmine/jasmine/issues/1712) from @johnjbarton
* PrettyPrinter handles objects with invalid toString implementations
- Merges [#1711](https://github.com/jasmine/jasmine/issues/1711) from @elliot-nelson
- Closes [#1700](https://github.com/jasmine/jasmine/issues/1700)
- Closes [#1575](https://github.com/jasmine/jasmine/issues/1575)
* Fix toBeCloseTo matcher for Node.js 12 and Chrome 74
- Merges [#1710](https://github.com/jasmine/jasmine/issues/1710) from @paulvanbrenk
- Fixes [#1695](https://github.com/jasmine/jasmine/issues/1695)
* spyOnProperty jasmine-style error messages with usage note
- Merges [#1706](https://github.com/jasmine/jasmine/issues/1706) from @elliot-nelson
* spyOnProperty respects the allowRespy flag
- Merges [#1705](https://github.com/jasmine/jasmine/issues/1705) from @elliot-nelson
* Introduce matchers#toBeInstanceOf
- Merges [#1697](https://github.com/jasmine/jasmine/issues/1697) from @elliot-nelson
* Print global errors encountered during CI runs
- Merges [#1701](https://github.com/jasmine/jasmine/issues/1701) from @elliot-nelson
* Update contributing doc based on some of the newer tooling
- Fixes [#1702](https://github.com/jasmine/jasmine/issues/1702)
* Extend spyOnAllFunctions to include prototype and parent methods
- Merges [#1699](https://github.com/jasmine/jasmine/issues/1699) from @elliot-nelson
- Fixes [#1677](https://github.com/jasmine/jasmine/issues/1677)
* Improve error handling in CI test launcher
- Merges [#1598](https://github.com/jasmine/jasmine/issues/1598) from @elliot-nelson
* Add new spy strategies to resolve and reject Promises `resolveTo` and `rejectWith`
- Merges [#1688](https://github.com/jasmine/jasmine/issues/1688) from @enelson
- See [#1590](https://github.com/jasmine/jasmine/issues/1590)
- Fixes [#1715](https://github.com/jasmine/jasmine/issues/1715)
* Update deprecation messages to indicate _future_ removal
- Fixes [#1628](https://github.com/jasmine/jasmine/issues/1628)
* Add toBeRejectedWithError matcher
- Merges [#1686](https://github.com/jasmine/jasmine/issues/1686) from @megahertz
- Fixes [#1625](https://github.com/jasmine/jasmine/issues/1625)
* Ignore internal ci.js from npm package
- See [#1684](https://github.com/jasmine/jasmine/issues/1684)
* Fix failure messages for positive/negative infinity matchers
- Fixes [#1674](https://github.com/jasmine/jasmine/issues/1674)
* nit: fix typo
- Merges [#1680](https://github.com/jasmine/jasmine/issues/1680) from @acinader
* added #toBeTrue and #toBeFalse matchers
- Merges [#1679](https://github.com/jasmine/jasmine/issues/1679) from @FelixRilling
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

146
release_notes/3.6.0.md Normal file
View File

@@ -0,0 +1,146 @@
# Jasmine Core 3.6 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes.
## Highlights
* Added support for custom object formatters
* Allows customizing how an object is stringified in matcher failure messages
* [Tutorial](https://jasmine.github.io/tutorials/custom_object_formatter)
* [API reference](https://jasmine.github.io/api/3.6/jasmine.html#.addCustomObjectFormatter)
* Don't require matchers and asymmetric equality testers to pass custom object formatters back to Jasmine
- Supports custom object formatters.
- Makes it easier to write high quality matchers and asymmetric equality testers.
- The old API will still work until 4.0.
* Properly import jasmineRequire object before using
- Improves compatibility with Webpack
- Merges [#1766](https://github.com/jasmine/jasmine/pull/1766) from @amilligan
* Added a toHaveBeenCalledOnceWith matcher
- Merges [#1801](https://github.com/jasmine/jasmine/pull/1801) from @Maximaximum
- Fixes [#1717](https://github.com/jasmine/jasmine/issues/1717)
* Added a toHaveSize matcher
- Merges [#1796](https://github.com/jasmine/jasmine/pull/1796) from @wokier
* Added a toBePending async matcher
- Merges [#1808](https://github.com/jasmine/jasmine/pull/1808) from @DCtheTall
- Fixes [#1803](https://github.com/jasmine/jasmine/issues/1803)
* Added support for user-defined spec/suite properties
- Allows specs/suites to pass data to custom reporters
- Merges [#1763](https://github.com/jasmine/jasmine/pull/1763) from @johnjbarton
* Route unhandled promise rejections to onerror
- Merges [#1778](https://github.com/jasmine/jasmine/pull/1778) from @johnjbarton
- Fixes [#1777](https://github.com/jasmine/jasmine/issues/1777)
## Internal notes
* Use a version of eslint that works on Node 8
* Check for syntax and standard library objects that don't work in IE
* Run eslint against all files
* Add Additional Test for equals Matcher
- Merges [#1829](https://github.com/jasmine/jasmine/pull/1829) from @tobiasschweizer
- Fixes [#1821](https://github.com/jasmine/jasmine/issues/1821)
* Depend on head of jasmine-browser to fix IE failures in CI
* Fixed test failure in Firefox 74
* Added test for resolveTo/rejectWith with empty parameters
- Merges [#1802](https://github.com/jasmine/jasmine/pull/1802) from @chivesrs
* Removed unnecessary uses of new in tests
* Realigned the browser testing matrix to match current reality
- Use Windows instead of Linux so we can get current browsers from Sauce.
- Test against the version of Firefox that corresponds to ESR as well as
latest.
- Test the latest Edge rather than a specific older version.
- Test Safari 8 and 13 instead of 8, 9 and 10. What works in those versions
is likely to work in the ones in between.
* Don't leak global error handlers between Jasmine's own tests
* Added basic property tests for matchersUtil.equals
* Added integration tests for existing matcher interfaces
* Added integration tests for asymmetric equality testers
* Test IE before other browsers on Travis
## Other Changes
* Show diffs involving root-level asymmetric equality testers
- Fixes [#1831](https://github.com/jasmine/jasmine/issues/1831)
* Fixed references to master in docs
* Allow spy throwError to throw an Object
- Merges [#1822](https://github.com/jasmine/jasmine/pull/1822) from @terencehonles
* Added missing periods to README
- Merges [#1828](https://github.com/jasmine/jasmine/pull/1828) from @dirkpuge
* Expose setSpec/SuiteProperty on interface
- Merges [#1820](https://github.com/jasmine/jasmine/pull/1820) from @johnjbarton
* Prevent undesired reloads when karma-jasmine-html-reporter is used
- Merges [#1807](https://github.com/jasmine/jasmine/pull/1807) from @parloti
- Fixes [#1775](https://github.com/jasmine/jasmine/issues/1775)
* Correctly report spec and suite duration
- Fixes [#1676](https://github.com/jasmine/jasmine/issues/1676).
* Added jsdocs for MatchersUtil
* Allow the .callThrough spy strategy to call constructor functions without errors
- Merges [#1782](https://github.com/jasmine/jasmine/pull/1782) from @enelson
- Fixes [#1760](https://github.com/jasmine/jasmine/issues/1760)
* Inject a per-runable pretty printer into MatchersUtil
- Supports custom object formatters
* Include stack traces in unhandled promise rejection messages
* Describe the naming for the function it
- Merges [#1772](https://github.com/jasmine/jasmine/pull/1772) from @johnlinp
* Correctly extract error messages from stack traces that don't start with `Error`
- Merges [#1776](https://github.com/jasmine/jasmine/pull/1776) from @vhermannitk
- Fixes [#1771](https://github.com/jasmine/jasmine/issues/1771)
* Fixed objectContaining to not match when the expected is the empty object and the actual is a non-object
* Fixed toEqual(0, Number.MIN_VALUE) to fail instead of passing
- Merges [#1764](https://github.com/jasmine/jasmine/pull/1764) from @dubzzz
* Fixed comparison between ObjectContaining and non-objects on IE
* Provide better diffs for object graphs that include `objectContaining`
* Indent multiline failure messages in the output of `withContext`
* This makes it easier to see where each failure message begins and ends.
* Report async expectations that complete after the runable completes
- See [#1752](https://github.com/jasmine/jasmine/issues/1752).
* Treat NodeJS assertion failures as expectation failures
- Merges [#1678](https://github.com/jasmine/jasmine/pull/1678) from @apla
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

80
release_notes/3.7.0.md Normal file
View File

@@ -0,0 +1,80 @@
# Jasmine Core 3.7 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes.
## New features and bug fixes
* Allow custom object formatters to be added in beforeAll
- Fixes [#1876](http://github.com/jasmine/jasmine/issues/1876)
* Allow specs to disable Jasmine's global error handling by overwriting `onerror`.
- Merges [#1860](https://github.com/jasmine/jasmine/pull/1860) from @greghuc
* Fixed comparison between URL objects
- Fixes [#1866](http://github.com/jasmine/jasmine/issues/1866)
* Added support for stack traces created by `node --enable-source-maps`
with tools like the Typescript compiler.
- Merges [#1862](https://github.com/jasmine/jasmine/pull/1862) from @JannesMeyer
* Made properties added by createSpyObj() enumerable.
- Merges [#1859](https://github.com/jasmine/jasmine/pull/1859) from DCtheTall
- Fixes [#1837](http://github.com/jasmine/jasmine/issues/1837)
* Show the name of the spec/suite that caused a deprecation
* Warn if a spec or before/after function both takes a callback and returns a promise
* Don't overwrite MatchersUtil methods with ones that were added to
`Array.prototype`, esp. `contains`
- Fixes [#1849](http://github.com/jasmine/jasmine/issues/1849)
* Allow generator functions to be passed to `.and.callFake`
- Fixes [#1848](http://github.com/jasmine/jasmine/issues/1848)
## Documentation updates
* Fixed instructions for contributors to run Jasmine's ci script
* Updated supported Node versions in README
* Fixed script and CSS URLs in standalone example in README
- Merges [#1839](https://github.com/jasmine/jasmine/pull/1839) from @snowman
* Fixed typo in asyncMatcher toBePending comment
- Merges [#1847](https://github.com/jasmine/jasmine/pull/1847) from @SnailCoil
* Fixed link to custom object formatter tutorial
* Added jasmine.isSpy to the public interface
- Fixes [#1880](http://github.com/jasmine/jasmine/issues/1880)
## Internal notes
* Fixed intermittent test failures
* Added additional assertions to tests for toBeTruthy and toBeFalsy
- Merges [#1875](https://github.com/jasmine/jasmine/pull/1875) from @yasinkocak
* Pointed Travis badge at travis-ci.com, not .org
* Fixed file globs so that Prettier runs on all files
* Check for forgotten console and debugger statements
* Fixed code in Jasmine that will trigger deprecations in 3.99
* Use jasmine-browser from npm rather than from the main branch
- The current released version now works with IE, so we no longer need to
depend on main.
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

8
release_notes/3.7.1.md Normal file
View File

@@ -0,0 +1,8 @@
# Jasmine Core 3.7.1 Release Notes
## Summary
This is a bug fix release of Jasmine. It's identical to 3.7.0 except that it
correctly reports its version number. Please see the
[3.7.0 release notes](https://github.com/jasmine/jasmine/blob/main/release_notes/3.7.0.md)
if you're upgrading directly from 3.6.0 or earlier.

132
release_notes/3.8.0.md Normal file
View File

@@ -0,0 +1,132 @@
# Jasmine Core 3.8 Release Notes
## Summary
This is a maintenance release of Jasmine with a number of new features and fixes.
## Python deprecation
The Jasmine packages for Python are deprecated. We intend to continue releasing
them through the end of the 3.x series, but after that they will be
discontinued. We recommend migrating to the following alternatives:
* The [jasmine-browser-runner](https://github.com/jasmine/jasmine-browser)
npm package to run specs in browsers, including headless Chrome and
Saucelabs. This is the most direct replacement for the `jasmine server`
and `jasmine ci` commands provided by the `jasmine` Python package.
* The [jasmine](https://github.com/jasmine/jasmine-npm) npm package (
`npm install jasmine`) to run specs under Node.js.
* The standalone distribution from the
[latest Jasmine release](https://github.com/jasmine/jasmine/releases) to
run specs in browsers with no additional tools.
* The [jasmine-core](https://github.com/jasmine/jasmine) npm package if all
you need is the Jasmine assets. This is the direct equivalent of the
jasmine-core Python package.
## New features and bug fixes
* Fixed spec filtering in Karma
* Merges [#1920](https://github.com/jasmine/jasmine/pull/1920) from @jlpstolwijk
* Fixes [#1906](https://github.com/jasmine/jasmine/issues/1906)
* Added expectAsync(...).already
* Causes async matchers to immediately fail if the promise is pending
* See https://jasmine.github.io/api/3.8/async-matchers.html#already
* Fixes [#1845](https://github.com/jasmine/jasmine/issues/1845)
* Include rejection details in failure messages for toBeResolved and toBeResolvedWith
* Fixed "stop spec on expectation failure" checkbox in standalone
* Added option for spyOnAllFunctions to include non-enumerable props
* Makes spyOnAllFunctions work on instance methods of ES6 classes
* Merges [#1909](https://github.com/jasmine/jasmine/pull/1909) from @Dari-k
* Fixes [#1897](https://github.com/jasmine/jasmine/issues/1897)
* Added Spy#calls#thisFor
* Provides the `this` value for a given spy call
* Merges [#1903](https://github.com/jasmine/jasmine/pull/1903) from @ajvincent
* Improved handling of unhandled promise rejections with no error in Node
* Fixes [#1759](https://github.com/jasmine/jasmine/issues/1759)
## Documentation updates
* Updated package description
* Updated contributing guide
* Added TypeScript typings and jasmine-browser-runner to issue template
* Removed constructors from jsdocs of classes that aren't user-constructable
* Fixed config.seed type in jsdocs
* Merges [#1892](https://github.com/jasmine/jasmine/pull/1892) from @UziTech
* Added jsdocs for the following:
* asymmetric equality testers
* Env#execute
* Env#allowRespy
* The public portion of Spec
* Spy.callData.returnValue
* Env#topSuite and Suite
* Added a jsdoc cross-reference from Configuration to its usage
* Added a note about correct usage of async matchers
* Added support for ArrayBuffers to matchersUtil.equals
* Merges [#1891](https://github.com/jasmine/jasmine/pull/1892) from @Finesse
* Merges [#1689](https://github.com/jasmine/jasmine/pull/1892) from @dankurka
* Fixes [#1687](https://github.com/jasmine/jasmine/issues/1687)
## Internal notes
* Fixed typo in spec name
* Merges [#1918](https://github.com/jasmine/jasmine/pull/1918) from @eltociear
* Specify files to include in the NPM package rather than files to exclude
* Added test coverage for MatchersUtil#equals with typed arrays
* Removed checks for typed array support in the test suite
* All supported browsers have all typed arrays except for Uint8ClampedArray,
BigInt64Array, and BigUint64Array.
* Fixed test failures on IE 10
* Test matrix updates
* Added Node 16
* Added Safari 14
* Added Firefox 78 (closest match to current ESR)
* Removed Safari 10-12 to speed up CI. The newer and older versions we test
provide a good measure of safety.
* Replaced node-sass dev dependency that isn't compatible with Node 16
* Removed unused dev dependencies
* Migrated CI from Travis to Circle
* Compensate for clock jitter in specs
## Supported environments
jasmine-core 3.8.0 has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------|
| Node | 10, 12, 14, 16 |
| Safari | 8-14 |
| Chrome | 91 |
| Firefox | 89, 68, 78 |
| Edge | 91 |
| Internet Explorer | 10, 11 |
------
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

65
release_notes/3.9.0.md Normal file
View File

@@ -0,0 +1,65 @@
# Jasmine Core 3.9 Release Notes
## New features and bug fixes
* Fixed Trusted Types error in `j$.isError_` in Chromium-based browsers
* Merges [#1921](https://github.com/jasmine/jasmine/pull/1921) from @bjarkler
* Fixes [#1910](https://github.com/jasmine/jasmine/issues/1910)
* Fixes [#1653](https://github.com/jasmine/jasmine/issues/1653)
* Better reporting of unhandled promise rejections with truthy but non-`Error`
reasons on Node
* `Env#execute` returns a promise in environments that support promises
* Renamed `failFast` and `oneFailurePerSpec` config props to `stopOnSpecFailure`
and `stopSpecOnExpectationFailure`
The new names are more self-explanatory and consistent with jasmine-npm. The
old names are deprecated but will still work until the next major release.
* Split `boot.js` into two files to allow the env to be configured in between
This is mainly intended to support jasmine-browser-runner, which will load
a script that configures the env in between the two boot files (`boot0.js` and
`boot1.js`). The single-file `boot.js` will still be included until the next
major release.
## Ruby deprecation
The Jasmine Ruby gems are deprecated. There will be no further releases after
the end of the Jasmine 3.x series. We recommend that most users migrate to the
[jasmine-browser-runner](https://github.com/jasmine/jasmine-browser)
npm package, which is the direct replacement for the `jasmine` gem.
If `jasmine-browser-runner` doesn't meet your needs, one of these might:
* The [jasmine](https://github.com/jasmine/jasmine-npm) npm package to run
specs in Node.js.
* The [standalone distribution](https://github.com/jasmine/jasmine#installation)
to run specs in browsers with no additional tools.
* The [jasmine-core](https://github.com/jasmine/jasmine) npm package if all
you need is the Jasmine assets. This is the direct equivalent of the
`jasmine-core` Ruby gem.
## Documentation updates
* Added API docs for `Suite#id` and `Spec#id`
* Marked `Env#hideDisabled` deprecated in jsdocs
------
## Supported environments
jasmine-core 3.9.0 has been tested in the following environments.
| Environment | Supported versions |
|-------------------|--------------------|
| Node | 10, 12, 14, 16 |
| Safari | 8-14 |
| Chrome | 92 |
| Firefox | 91, 78, 68 |
| Edge | 92 |
| Internet Explorer | 10, 11 |
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_

43
scripts/run-all-browsers Executable file
View File

@@ -0,0 +1,43 @@
#!/bin/sh
run_browser() {
browser=$1
version=$2
description="$browser $version"
if [ $version = "latest" ]; then
version=""
fi
echo
echo
echo "Running $description"
echo
USE_SAUCE=true JASMINE_BROWSER=$browser SAUCE_BROWSER_VERSION=$version npm run ci
if [ $? -eq 0 ]; then
echo "PASS: $description" >> "$passfile"
else
echo "FAIL: $description" >> "$failfile"
fi
}
passfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
failfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
run_browser "internet explorer" 11
run_browser "internet explorer" 10
run_browser chrome latest
run_browser firefox latest
run_browser firefox 78
run_browser firefox 68
run_browser safari 14
run_browser safari 13
run_browser safari 9
run_browser safari 8
run_browser MicrosoftEdge latest
echo
cat "$passfile" "$failfile"
if [ -s "$failfile" ]; then
exit 1
fi

37
scripts/start-sauce-connect Executable file
View File

@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
if [ $# -gt 1 -o "$1" = "--help" ]; then
echo "Usage: $0 [pidfile]" 1>&2
exit
fi
if [ -z "$1" ]; then
pidfile=`mktemp`
else
pidfile="$1"
fi
outfile=`mktemp`
echo "Starting Sauce Connect"
if [ -z "$SAUCE_TUNNEL_IDENTIFIER" ]; then
sc -u "$SAUCE_USERNAME" -k "$SAUCE_ACCESS_KEY" -X 4445 --pidfile "$pidfile" 2>&1 | tee "$outfile" &
else
sc -u "$SAUCE_USERNAME" -k "$SAUCE_ACCESS_KEY" -X 4445 --pidfile "$pidfile" -i "$SAUCE_TUNNEL_IDENTIFIER" 2>&1 | tee "$outfile" &
fi
while ! fgrep "Sauce Connect is up, you may start your tests." "$outfile" > /dev/null; do
sleep 1
if ! ps -p $(cat "$pidfile") > /dev/null; then
echo "Sauce Connect exited"
exit 1
fi
done
if ! nc -z localhost 4445; then
echo "Can't connect to Sauce tunnel"
killall sc
exit 1
fi

33
scripts/stop-sauce-connect Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -o errexit
set -o pipefail
if [ -z "$1" ]; then
echo "Usage: $0 sauce-connect-pid" 1>&2
exit
fi
pid="$1"
echo "PID: $pid"
echo "Stopping Sauce Connect"
# Sauce Connect docs say that we can just kill -9 it if we don't care about
# failing any ongoing sessions. In practice, that sometimes works but usually
# leaks a tunnel so badly that you can't even stop it from the web UI.
# Instead of doing that, we give Sauce Connect some time to shut down
# gracefully and then give up.
kill -INT $pid
# Wait up to 2 minutes, then give up if it's still running
n=0
while [ $n -lt 120 ] && ps -p $pid > /dev/null; do
sleep 1
kill -INT $pid 2> /dev/null || true
n=$(($n + 1))
done
if ps -p $pid > /dev/null; then
echo "Could not shut down Sauce Connect"
fi
exit $exitcode

View File

@@ -4,15 +4,41 @@ import json
with open('package.json') as packageFile:
version = json.load(packageFile)['version']
short_description=('Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on '+
'browsers, DOM, or any JavaScript framework. Thus it\'s suited for websites, '+
'Node.js (http://nodejs.org) projects, or anywhere that JavaScript can run.')
deprecation=('The Jasmine packages for Python are deprecated. There will be no further\n' +
'releases after the end of the Jasmine 3.x series. We recommend migrating to the\n' +
'following options:\n' +
'\n' +
'* jasmine-browser-runner (<https://github.com/jasmine/jasmine-browser>,\n' +
' `npm install jasmine-browser-runner`) to run specs in browsers, including\n' +
' headless Chrome and Saucelabs. This is the most direct replacement for the\n' +
' jasmine server` and `jasmine ci` commands provided by the `jasmine` Python\n' +
' package.\n' +
'* The jasmine npm package (<https://github.com/jasmine/jasmine-npm>,\n' +
' `npm install jasmine`) to run specs under Node.js.\n' +
'* The standalone distribution from the latest Jasmine release\n' +
' <https://github.com/jasmine/jasmine/releases> to run specs in browsers with\n' +
' no additional tools.\n' +
'* The jasmine-core npm package (`npm install jasmine-core`) if all you need is\n' +
' the Jasmine assets. This is the direct equivalent of the jasmine-core Python\n' +
' package.\n' +
'\n' +
'Except for the standalone distribution, all of the above are distributed through\n'
'npm.\n')
long_description = short_description + '\n\n' + deprecation
setup(
name="jasmine-core",
version=version,
url="http://jasmine.github.io",
author="Pivotal Labs",
author_email="jasmine-js@googlegroups.com",
description=('Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on '+
'browsers, DOM, or any JavaScript framework. Thus it\'s suited for websites, '+
'Node.js (http://nodejs.org) projects, or anywhere that JavaScript can run.'),
description=short_description,
long_description=long_description,
long_description_content_type='text/plain',
license='MIT',
classifiers=[
'Development Status :: 5 - Production/Stable',
@@ -23,9 +49,6 @@ setup(
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',

20
spec/.eslintrc.js Normal file
View File

@@ -0,0 +1,20 @@
module.exports = {
ignorePatterns: ['support/ci.js', 'support/jasmine-browser.js'],
rules: {
// Relax rules for now to allow for the quirks of the test suite
// TODO: We should probably remove these & fix the resulting errors
quotes: 'off',
semi: 'off',
'key-spacing': 'off',
'space-before-blocks': 'off',
'no-unused-vars': 'off',
'no-trailing-spaces': 'off',
'block-spacing': 'off',
// Since linting is done at the end of the process and doesn't stop us
// from running tests, it makes sense to fail if debugger statements
// or console references are present.
'no-debugger': 'error',
'no-console': 'error'
}
};

View File

@@ -1,270 +0,0 @@
describe("ConsoleReporter", function() {
var out;
beforeEach(function() {
out = (function() {
var output = "";
return {
print: function(str) {
output += str;
},
getOutput: function() {
return output.replace('ConsoleReporter is deprecated and will be removed in a future version.', '');
},
clear: function() {
output = "";
}
};
}());
});
it("reports that the suite has started to the console", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("starts the provided timer when jasmine starts", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
expect(timerSpy.start).toHaveBeenCalled();
});
it("reports a passing spec as a dot", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual(".");
});
it("does not report a disabled spec", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "disabled"});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "failed"});
expect(out.getOutput()).toEqual("F");
});
it("reports a pending spec as a '*'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.specDone({status: "pending"});
expect(out.getOutput()).toEqual("*");
});
it("alerts user if there are no specs", function(){
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/No specs found/);
});
it("reports a summary when done (singular spec and time)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
timerSpy.elapsed.and.returnValue(1000);
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/1 spec, 0 failures/);
expect(out.getOutput()).not.toMatch(/0 pending specs/);
expect(out.getOutput()).toMatch("Finished in 1 second\n");
});
it("reports a summary when done (pluralized specs and seconds)", function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
timer: timerSpy
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({status: "pending"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo\nbar\nbaz"
}
]
});
out.clear();
timerSpy.elapsed.and.returnValue(100);
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/3 specs, 1 failure, 1 pending spec/);
expect(out.getOutput()).toMatch("Finished in 0.1 seconds\n");
});
it("reports a summary when done that includes stack traces for a failing suite", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print
});
reporter.jasmineStarted();
reporter.specDone({status: "passed"});
reporter.specDone({
status: "failed",
description: "with a failing spec",
fullName: "A suite with a failing spec",
failedExpectations: [
{
passed: false,
message: "Expected true to be false.",
expected: false,
actual: true,
stack: "foo bar baz"
}
]
});
out.clear();
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/true to be false/);
expect(out.getOutput()).toMatch(/foo bar baz/);
});
describe('onComplete callback', function(){
var onComplete, reporter;
beforeEach(function() {
onComplete = jasmine.createSpy('onComplete');
reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
onComplete: onComplete
});
reporter.jasmineStarted();
});
it("is called when the suite is done", function() {
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(true);
});
it('calls it with false if there are spec failures', function() {
reporter.specDone({status: "failed", failedExpectations: []});
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(false);
});
it('calls it with false if there are suite failures', function() {
reporter.specDone({status: "passed"});
reporter.suiteDone({failedExpectations: [{ message: 'bananas' }] });
reporter.jasmineDone();
expect(onComplete).toHaveBeenCalledWith(false);
});
});
describe("with color", function() {
it("reports that the suite has started to the console", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.jasmineStarted();
expect(out.getOutput()).toEqual("Started\n");
});
it("reports a passing spec as a dot", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: "passed"});
expect(out.getOutput()).toEqual("\x1B[32m.\x1B[0m");
});
it("does not report a disabled spec", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: 'disabled'});
expect(out.getOutput()).toEqual("");
});
it("reports a failing spec as an 'F'", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.specDone({status: 'failed'});
expect(out.getOutput()).toEqual("\x1B[31mF\x1B[0m");
});
it("displays all afterAll exceptions", function() {
var reporter = new jasmineUnderTest.ConsoleReporter({
print: out.print,
showColors: true
});
reporter.suiteDone({ failedExpectations: [{ message: 'After All Exception' }] });
reporter.suiteDone({ failedExpectations: [{ message: 'Some Other Exception' }] });
reporter.jasmineDone();
expect(out.getOutput()).toMatch(/After All Exception/);
expect(out.getOutput()).toMatch(/Some Other Exception/);
});
});
});

View File

@@ -0,0 +1,849 @@
/* eslint-disable compat/compat */
describe('AsyncExpectation', function() {
beforeEach(function() {
jasmineUnderTest.Expectation.addAsyncCoreMatchers(
jasmineUnderTest.asyncMatchers
);
});
describe('Factory', function() {
it('throws an Error if promises are not available', function() {
var thenable = { then: function() {} },
options = { global: {}, actual: thenable };
function f() {
jasmineUnderTest.Expectation.asyncFactory(options);
}
expect(f).toThrowError(
'expectAsync is unavailable because the environment does not support promises.'
);
});
});
describe('#not', function() {
it('converts a pass to a fail', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
pp = jasmineUnderTest.makePrettyPrinter(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp }),
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
passed: false,
message: 'Expected [object Promise] not to be resolved.'
})
);
});
});
it('converts a fail to a pass', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
matchersUtil: new jasmineUnderTest.MatchersUtil({
pp: function() {}
}),
actual: actual,
addExpectationResult: addExpectationResult
});
return expectation.not.toBeResolved().then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
true,
jasmine.objectContaining({
passed: true,
message: ''
})
);
});
});
});
it('propagates rejections from the comparison function', function() {
jasmine.getEnv().requirePromises();
var error = new Error('ExpectationSpec failure');
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = dummyPromise(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult
});
spyOn(expectation, 'toBeResolved').and.returnValue(Promise.reject(error));
return expectation.toBeResolved().then(
function() {
fail('Expected a rejection');
},
function(e) {
expect(e).toBe(error);
}
);
});
describe('#withContext', function() {
it('prepends the context to the generated failure message', function() {
jasmine.getEnv().requirePromises();
var matchersUtil = {
pp: function(val) {
return val.toString();
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('rejected'),
addExpectationResult: addExpectationResult,
matchersUtil: matchersUtil
});
return expectation
.withContext('Some context')
.toBeResolved()
.then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message:
'Some context: Expected a promise to be resolved but it was rejected with rejected.'
})
);
});
});
it('prepends the context to a custom failure message', function() {
jasmine.getEnv().requirePromises();
var matchersUtil = {
buildFailureMessage: function() {
return 'failure message';
},
pp: jasmineUnderTest.makePrettyPrinter()
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: Promise.reject('b'),
addExpectationResult: addExpectationResult,
matchersUtil: matchersUtil
});
return expectation
.withContext('Some context')
.toBeResolvedTo('a')
.then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message:
"Some context: Expected a promise to be resolved to 'a' " +
"but it was rejected with 'b'."
})
);
});
});
it('prepends the context to a custom failure message from a function', function() {
pending('should actually work, but no custom matchers for async yet');
jasmine.getEnv().requirePromises();
var matchersUtil = {
buildFailureMessage: function() {
return 'failure message';
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.reject(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
matchersUtil: matchersUtil
});
return expectation
.withContext('Some context')
.toBeResolved()
.then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: 'Some context: msg'
})
);
});
});
it('works with #not', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve(),
pp = jasmineUnderTest.makePrettyPrinter(),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp })
});
return expectation
.withContext('Some context')
.not.toBeResolved()
.then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message:
'Some context: Expected [object Promise] not to be resolved.'
})
);
});
});
it('works with #not and a custom message', function() {
jasmine.getEnv().requirePromises();
var addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = Promise.resolve('a'),
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: actual,
addExpectationResult: addExpectationResult,
matchersUtil: new jasmineUnderTest.MatchersUtil({
pp: jasmineUnderTest.makePrettyPrinter()
})
});
return expectation
.withContext('Some context')
.not.toBeResolvedTo('a')
.then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message:
"Some context: Expected a promise not to be resolved to 'a'."
})
);
});
});
});
describe('async matchers', function() {
it('makes custom matchers available to this expectation', function() {
jasmine.getEnv().requirePromises();
var asyncMatchers = {
toFoo: function() {},
toBar: function() {}
},
expectation;
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: asyncMatchers
});
expect(expectation.toFoo).toBeDefined();
expect(expectation.toBar).toBeDefined();
});
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
jasmine.getEnv().requirePromises();
var fakeCompare = function() {
return Promise.resolve({ pass: true });
},
matcherFactory = jasmine
.createSpy('matcher')
.and.returnValue({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
customEqualityTesters = ['a'],
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = jasmineUnderTest.Expectation.asyncFactory({
matchersUtil: matchersUtil,
customAsyncMatchers: matchers,
customEqualityTesters: customEqualityTesters,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(matcherFactory).toHaveBeenCalledWith(
matchersUtil,
customEqualityTesters
);
});
});
it("wraps matchers's compare functions, passing the actual and expected", function() {
jasmine.getEnv().requirePromises();
var fakeCompare = jasmine
.createSpy('fake-compare')
.and.returnValue(Promise.resolve({ pass: true })),
matchers = {
toFoo: function() {
return {
compare: fakeCompare
};
}
},
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = jasmineUnderTest.Expectation.asyncFactory({
matchersUtil: matchersUtil,
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(fakeCompare).toHaveBeenCalledWith('an actual', 'hello');
});
});
it('reports a passing result to the spec when the comparison passes', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: true });
}
};
}
},
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
matchersUtil: matchersUtil,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toFoo',
passed: true,
message: '',
error: undefined,
expected: 'hello',
actual: 'an actual',
errorForStack: errorWithStack
});
});
});
it('reports a failing result to the spec when the comparison fails', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: false });
}
};
}
},
matchersUtil = {
buildFailureMessage: function() {
return '';
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
matchersUtil: matchersUtil,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: '',
error: undefined,
errorForStack: errorWithStack
});
});
});
it('reports a failing result and a custom fail message to the spec when the comparison fails', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: false,
message: 'I am a custom message'
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: 'an actual',
customAsyncMatchers: matchers,
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it('reports a failing result with a custom fail message function to the spec when the comparison fails', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: false,
message: function() {
return 'I am a custom message';
}
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it('reports a passing result to the spec when the comparison fails for a negative expectation', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: false });
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toFoo',
passed: true,
message: '',
error: undefined,
expected: 'hello',
actual: actual,
errorForStack: errorWithStack
});
});
});
it('reports a failing result to the spec when the comparison passes for a negative expectation', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: true });
}
};
}
},
matchersUtil = {
buildFailureMessage: function() {
return 'default message';
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
matchersUtil: matchersUtil,
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: actual,
message: 'default message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it('reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation', function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: true,
message: 'I am a custom message'
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: actual,
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it("reports a passing result to the spec when the 'not' comparison passes, given a negativeCompare", function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: true });
},
negativeCompare: function() {
return Promise.resolve({ pass: true });
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: 'toFoo',
passed: true,
expected: 'hello',
actual: actual,
message: '',
error: undefined,
errorForStack: errorWithStack
});
});
});
it("reports a failing result and a custom fail message to the spec when the 'not' comparison fails, given a negativeCompare", function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({ pass: true });
},
negativeCompare: function() {
return Promise.resolve({
pass: false,
message: "I'm a custom message"
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
customAsyncMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: actual,
message: "I'm a custom message",
error: undefined,
errorForStack: errorWithStack
});
});
});
it('reports errorWithStack when a custom error message is returned', function() {
jasmine.getEnv().requirePromises();
var customError = new Error('I am a custom error');
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: false,
message: 'I am a custom message',
error: customError
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: 'an actual',
customAsyncMatchers: matchers,
addExpectationResult: addExpectationResult
});
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it("reports a custom message to the spec when a 'not' comparison fails", function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: true,
message: 'I am a custom message'
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: 'an actual',
customAsyncMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
jasmine.getEnv().requirePromises();
var matchers = {
toFoo: function() {
return {
compare: function() {
return Promise.resolve({
pass: true,
message: function() {
return 'I am a custom message';
}
});
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
errorWithStack = new Error('errorWithStack'),
expectation;
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
errorWithStack
);
expectation = jasmineUnderTest.Expectation.asyncFactory({
actual: 'an actual',
customAsyncMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
return expectation.toFoo('hello').then(function() {
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: errorWithStack
});
});
});
});
function dummyPromise() {
return new Promise(function(resolve, reject) {});
}
});

View File

@@ -1,5 +1,5 @@
describe("CallTracker", function() {
it("tracks that it was called when executed", function() {
describe('CallTracker', function() {
it('tracks that it was called when executed', function() {
var callTracker = new jasmineUnderTest.CallTracker();
expect(callTracker.any()).toBe(false);
@@ -9,7 +9,7 @@ describe("CallTracker", function() {
expect(callTracker.any()).toBe(true);
});
it("tracks that number of times that it is executed", function() {
it('tracks that number of times that it is executed', function() {
var callTracker = new jasmineUnderTest.CallTracker();
expect(callTracker.count()).toEqual(0);
@@ -19,52 +19,66 @@ describe("CallTracker", function() {
expect(callTracker.count()).toEqual(1);
});
it("tracks the params from each execution", function() {
it('tracks the params from each execution', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track({object: void 0, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: void 0, args: [] });
callTracker.track({ object: {}, args: [0, 'foo'] });
expect(callTracker.argsFor(0)).toEqual([]);
expect(callTracker.argsFor(1)).toEqual([0, "foo"]);
expect(callTracker.argsFor(1)).toEqual([0, 'foo']);
});
it("returns any empty array when there was no call", function() {
it("tracks the 'this' object from each execution", function() {
var callTracker = new jasmineUnderTest.CallTracker();
var this0 = {},
this1 = {};
callTracker.track({ object: this0, args: [] });
callTracker.track({ object: this1, args: [] });
callTracker.track({ args: [] });
expect(callTracker.thisFor(0)).toBe(this0);
expect(callTracker.thisFor(1)).toBe(this1);
expect(callTracker.thisFor(2)).toBe(undefined);
});
it('returns any empty array when there was no call', function() {
var callTracker = new jasmineUnderTest.CallTracker();
expect(callTracker.argsFor(0)).toEqual([]);
});
it("allows access for the arguments for all calls", function() {
it('allows access for the arguments for all calls', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track({object: {}, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: {}, args: [] });
callTracker.track({ object: {}, args: [0, 'foo'] });
expect(callTracker.allArgs()).toEqual([[], [0, "foo"]]);
expect(callTracker.allArgs()).toEqual([[], [0, 'foo']]);
});
it("tracks the context and arguments for each call", function() {
it('tracks the context and arguments for each call', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track({object: {}, args: []});
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: {}, args: [] });
callTracker.track({ object: {}, args: [0, 'foo'] });
expect(callTracker.all()[0]).toEqual({object: {}, args: []});
expect(callTracker.all()[0]).toEqual({ object: {}, args: [] });
expect(callTracker.all()[1]).toEqual({object: {}, args: [0, "foo"]});
expect(callTracker.all()[1]).toEqual({ object: {}, args: [0, 'foo'] });
});
it("simplifies access to the arguments for the last (most recent) call", function() {
it('simplifies access to the arguments for the last (most recent) call', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track();
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: {}, args: [0, 'foo'] });
expect(callTracker.mostRecent()).toEqual({
object: {},
args: [0, "foo"]
args: [0, 'foo']
});
});
@@ -74,12 +88,12 @@ describe("CallTracker", function() {
expect(callTracker.mostRecent()).toBeFalsy();
});
it("simplifies access to the arguments for the first (oldest) call", function() {
it('simplifies access to the arguments for the first (oldest) call', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: {}, args: [0, 'foo'] });
expect(callTracker.first()).toEqual({object: {}, args: [0, "foo"]})
expect(callTracker.first()).toEqual({ object: {}, args: [0, 'foo'] });
});
it("returns a useful falsy value when there isn't a first (oldest) call", function() {
@@ -88,12 +102,11 @@ describe("CallTracker", function() {
expect(callTracker.first()).toBeFalsy();
});
it("allows the tracking to be reset", function() {
it('allows the tracking to be reset', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.track();
callTracker.track({object: {}, args: [0, "foo"]});
callTracker.track({ object: {}, args: [0, 'foo'] });
callTracker.reset();
expect(callTracker.any()).toBe(false);
@@ -103,14 +116,17 @@ describe("CallTracker", function() {
expect(callTracker.mostRecent()).toBeFalsy();
});
it("allows object arguments to be shallow cloned", function() {
it('allows object arguments to be shallow cloned', function() {
var callTracker = new jasmineUnderTest.CallTracker();
callTracker.saveArgumentsByValue();
var objectArg = {"foo": "bar"},
arrayArg = ["foo", "bar"];
var objectArg = { foo: 'bar' },
arrayArg = ['foo', 'bar'];
callTracker.track({object: {}, args: [objectArg, arrayArg, false, undefined, null, NaN, "", 0, 1.0]});
callTracker.track({
object: {},
args: [objectArg, arrayArg, false, undefined, null, NaN, '', 0, 1.0]
});
expect(callTracker.mostRecent().args[0]).not.toBe(objectArg);
expect(callTracker.mostRecent().args[0]).toEqual(objectArg);

View File

@@ -1,17 +1,23 @@
describe("ClearStack", function() {
it("works in an integrationy way", function(done) {
var clearStack = jasmineUnderTest.getClearStack(jasmineUnderTest.getGlobal());
describe('ClearStack', function() {
it('works in an integrationy way', function(done) {
var clearStack = jasmineUnderTest.getClearStack(
jasmineUnderTest.getGlobal()
);
clearStack(function() {
done();
});
});
it("uses setImmediate when available", function() {
var setImmediate = jasmine.createSpy('setImmediate').and.callFake(function(fn) { fn() }),
global = { setImmediate: setImmediate },
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
it('uses setImmediate when available', function() {
var setImmediate = jasmine
.createSpy('setImmediate')
.and.callFake(function(fn) {
fn();
}),
global = { setImmediate: setImmediate },
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
clearStack(function() {
called = true;
@@ -21,42 +27,50 @@ describe("ClearStack", function() {
expect(setImmediate).toHaveBeenCalled();
});
it("uses setTimeout instead of setImmediate every 10 calls to make sure we release the CPU", function() {
it('uses setTimeout instead of setImmediate every 10 calls to make sure we release the CPU', function() {
var setImmediate = jasmine.createSpy('setImmediate'),
setTimeout = jasmine.createSpy('setTimeout'),
global = { setImmediate: setImmediate, setTimeout: setTimeout },
clearStack = jasmineUnderTest.getClearStack(global);
setTimeout = jasmine.createSpy('setTimeout'),
global = { setImmediate: setImmediate, setTimeout: setTimeout },
clearStack = jasmineUnderTest.getClearStack(global);
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
expect(setImmediate).toHaveBeenCalled();
expect(setTimeout).not.toHaveBeenCalled();
clearStack(function() { });
clearStack(function() {});
expect(setImmediate.calls.count()).toEqual(9);
expect(setTimeout.calls.count()).toEqual(1);
clearStack(function() { });
clearStack(function() {});
expect(setImmediate.calls.count()).toEqual(10);
expect(setTimeout.calls.count()).toEqual(1);
});
it("uses MessageChannels when available", function() {
it('uses MessageChannels when available', function() {
var fakeChannel = {
port1: {},
port2: { postMessage: function() { fakeChannel.port1.onmessage(); } }
},
global = { MessageChannel: function() { return fakeChannel; } },
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
port1: {},
port2: {
postMessage: function() {
fakeChannel.port1.onmessage();
}
}
},
global = {
MessageChannel: function() {
return fakeChannel;
}
},
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
clearStack(function() {
called = true;
@@ -65,53 +79,66 @@ describe("ClearStack", function() {
expect(called).toBe(true);
});
it("uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU", function() {
it('uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU', function() {
var fakeChannel = {
port1: {},
port2: {
postMessage: jasmine.createSpy('postMessage').and.callFake(function() {
port1: {},
port2: {
postMessage: jasmine
.createSpy('postMessage')
.and.callFake(function() {
fakeChannel.port1.onmessage();
})
}
}
},
setTimeout = jasmine.createSpy('setTimeout'),
global = {
MessageChannel: function() {
return fakeChannel;
},
setTimeout = jasmine.createSpy('setTimeout'),
global = { MessageChannel: function() { return fakeChannel; }, setTimeout: setTimeout },
clearStack = jasmineUnderTest.getClearStack(global);
setTimeout: setTimeout
},
clearStack = jasmineUnderTest.getClearStack(global);
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() { });
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
clearStack(function() {});
expect(fakeChannel.port2.postMessage).toHaveBeenCalled();
expect(setTimeout).not.toHaveBeenCalled();
clearStack(function() { });
clearStack(function() {});
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(9);
expect(setTimeout.calls.count()).toEqual(1);
clearStack(function() { });
clearStack(function() {});
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(10);
expect(setTimeout.calls.count()).toEqual(1);
});
it("calls setTimeout when onmessage is called recursively", function() {
it('calls setTimeout when onmessage is called recursively', function() {
var fakeChannel = {
port1: {},
port2: { postMessage: function() { fakeChannel.port1.onmessage(); } }
port1: {},
port2: {
postMessage: function() {
fakeChannel.port1.onmessage();
}
}
},
setTimeout = jasmine.createSpy('setTimeout'),
global = {
MessageChannel: function() {
return fakeChannel;
},
setTimeout = jasmine.createSpy('setTimeout'),
global = {
MessageChannel: function() { return fakeChannel; },
setTimeout: setTimeout,
},
clearStack = jasmineUnderTest.getClearStack(global),
fn = jasmine.createSpy("second clearStack function");
setTimeout: setTimeout
},
clearStack = jasmineUnderTest.getClearStack(global),
fn = jasmine.createSpy('second clearStack function');
clearStack(function() {
clearStack(fn);
@@ -121,11 +148,13 @@ describe("ClearStack", function() {
expect(setTimeout).toHaveBeenCalledWith(fn, 0);
});
it("falls back to setTimeout", function() {
var setTimeout = jasmine.createSpy('setTimeout').and.callFake(function(fn) { fn() }),
global = { setTimeout: setTimeout },
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
it('falls back to setTimeout', function() {
var setTimeout = jasmine.createSpy('setTimeout').and.callFake(function(fn) {
fn();
}),
global = { setTimeout: setTimeout },
clearStack = jasmineUnderTest.getClearStack(global),
called = false;
clearStack(function() {
called = true;

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
describe("DelayedFunctionScheduler", function() {
it("schedules a function for later execution", function() {
describe('DelayedFunctionScheduler', function() {
it('schedules a function for later execution', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
@@ -12,9 +12,9 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("schedules a string for later execution", function() {
it('schedules a string for later execution', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
strfn = "horrible = true;";
strfn = 'horrible = true;';
scheduler.scheduleFunction(strfn, 0);
@@ -23,7 +23,7 @@ describe("DelayedFunctionScheduler", function() {
expect(horrible).toEqual(true);
});
it("#tick defaults to 0", function() {
it('#tick defaults to 0', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
@@ -36,7 +36,7 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("defaults delay to 0", function() {
it('defaults delay to 0', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
@@ -49,7 +49,7 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("optionally passes params to scheduled functions", function() {
it('optionally passes params to scheduled functions', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
@@ -62,7 +62,7 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalledWith('foo', 'bar');
});
it("scheduled fns can optionally reoccur", function() {
it('scheduled fns can optionally reoccur', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn');
@@ -81,23 +81,20 @@ describe("DelayedFunctionScheduler", function() {
scheduler.tick(21);
expect(fn.calls.count()).toBe(4);
});
it("increments scheduled fns ids unless one is passed", function() {
it('increments scheduled fns ids unless one is passed', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler();
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(2);
expect(scheduler.scheduleFunction(function() {
}, 0, [], false, 123)).toBe(123);
expect(scheduler.scheduleFunction(function() {
}, 0)).toBe(3);
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(1);
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(2);
expect(scheduler.scheduleFunction(function() {}, 0, [], false, 123)).toBe(
123
);
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(3);
});
it("#removeFunctionWithId removes a previously scheduled function with a given id", function() {
it('#removeFunctionWithId removes a previously scheduled function with a given id', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
timeoutKey;
@@ -113,7 +110,7 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).not.toHaveBeenCalled();
});
it("executes recurring functions interleaved with regular functions in the correct order", function() {
it('executes recurring functions interleaved with regular functions in the correct order', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
recurringCallCount = 0,
@@ -134,12 +131,12 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("schedules a function for later execution during a tick", function () {
it('schedules a function for later execution during a tick', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10;
scheduler.scheduleFunction(function () {
scheduler.scheduleFunction(function() {
scheduler.scheduleFunction(fn, fnDelay);
}, 0);
@@ -150,13 +147,13 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("#removeFunctionWithId removes a previously scheduled function with a given id during a tick", function () {
it('#removeFunctionWithId removes a previously scheduled function with a given id during a tick', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10,
timeoutKey;
scheduler.scheduleFunction(function () {
scheduler.scheduleFunction(function() {
scheduler.removeFunctionWithId(timeoutKey);
}, 0);
timeoutKey = scheduler.scheduleFunction(fn, fnDelay);
@@ -168,7 +165,7 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).not.toHaveBeenCalled();
});
it("executes recurring functions interleaved with regular functions and functions scheduled during a tick in the correct order", function () {
it('executes recurring functions interleaved with regular functions and functions scheduled during a tick in the correct order', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
recurringCallCount = 0,
@@ -185,7 +182,7 @@ describe("DelayedFunctionScheduler", function() {
scheduling = jasmine.createSpy('scheduling').and.callFake(function() {
expect(recurring.calls.count()).toBe(3);
expect(fn).not.toHaveBeenCalled();
scheduler.scheduleFunction(innerFn, 10); // 41ms absolute
scheduler.scheduleFunction(innerFn, 10); // 41ms absolute
});
scheduler.scheduleFunction(recurring, 10, [], true);
@@ -201,7 +198,7 @@ describe("DelayedFunctionScheduler", function() {
expect(innerFn).toHaveBeenCalled();
});
it("executes recurring functions after rescheduling them", function () {
it('executes recurring functions after rescheduling them', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
recurring = function() {
expect(scheduler.scheduleFunction).toHaveBeenCalled();
@@ -209,12 +206,12 @@ describe("DelayedFunctionScheduler", function() {
scheduler.scheduleFunction(recurring, 10, [], true);
spyOn(scheduler, "scheduleFunction");
spyOn(scheduler, 'scheduleFunction');
scheduler.tick(10);
});
it("removes functions during a tick that runs the function", function() {
it('removes functions during a tick that runs the function', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
spy = jasmine.createSpy('fn'),
spyAndRemove = jasmine.createSpy('fn'),
@@ -235,14 +232,14 @@ describe("DelayedFunctionScheduler", function() {
expect(spyAndRemove).toHaveBeenCalled();
});
it("removes functions during the first tick that runs the function", function() {
it('removes functions during the first tick that runs the function', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10,
timeoutKey;
timeoutKey = scheduler.scheduleFunction(fn, fnDelay, [], true);
scheduler.scheduleFunction(function () {
scheduler.scheduleFunction(function() {
scheduler.removeFunctionWithId(timeoutKey);
}, fnDelay);
@@ -257,8 +254,7 @@ describe("DelayedFunctionScheduler", function() {
it("does not remove a function that hasn't been added yet", function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
fn = jasmine.createSpy('fn'),
fnDelay = 10,
timeoutKey;
fnDelay = 10;
scheduler.removeFunctionWithId('foo');
scheduler.scheduleFunction(fn, fnDelay, [], false, 'foo');
@@ -270,17 +266,16 @@ describe("DelayedFunctionScheduler", function() {
expect(fn).toHaveBeenCalled();
});
it("updates the mockDate per scheduled time", function () {
it('updates the mockDate per scheduled time', function() {
var scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
tickDate = jasmine.createSpy('tickDate');
scheduler.scheduleFunction(function() {});
scheduler.scheduleFunction(function() {}, 1);
scheduler.scheduleFunction(function() {});
scheduler.scheduleFunction(function() {}, 1);
scheduler.tick(1, tickDate);
scheduler.tick(1, tickDate);
expect(tickDate).toHaveBeenCalledWith(0);
expect(tickDate).toHaveBeenCalledWith(1);
})
expect(tickDate).toHaveBeenCalledWith(0);
expect(tickDate).toHaveBeenCalledWith(1);
});
});

View File

@@ -1,53 +1,199 @@
// TODO: Fix these unit tests!
describe("Env", function() {
describe('Env', function() {
var env;
beforeEach(function() {
env = new jasmineUnderTest.Env();
});
describe("#pending", function() {
it("throws the Pending Spec exception", function() {
afterEach(function() {
env.cleanup_();
});
describe('#pending', function() {
it('throws the Pending Spec exception', function() {
expect(function() {
env.pending();
}).toThrow(jasmineUnderTest.Spec.pendingSpecExceptionMessage);
});
it("throws the Pending Spec exception with a custom message", function() {
it('throws the Pending Spec exception with a custom message', function() {
expect(function() {
env.pending('custom message');
}).toThrow(jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'custom message');
}).toThrow(
jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'custom message'
);
});
});
describe("#topSuite", function() {
it("returns the Jasmine top suite for users to traverse the spec tree", function() {
describe('#topSuite', function() {
it('returns the Jasmine top suite for users to traverse the spec tree', function() {
var suite = env.topSuite();
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
});
});
it('accepts its own current configureation', function() {
env.configure(env.configuration());
});
it('can configure specs to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({ oneFailurePerSpec: true });
spyOn(jasmineUnderTest, 'Spec');
env.it('foo', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: true
}));
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
jasmine.objectContaining({
throwOnExpectationFailure: true
})
);
});
it('can configure suites to throw errors on expectation failures', function() {
env.throwOnExpectationFailure(true);
env.configure({ oneFailurePerSpec: true });
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(jasmine.objectContaining({
throwOnExpectationFailure: true
}));
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(
jasmine.objectContaining({
throwOnExpectationFailure: true
})
);
});
describe('#describe', function () {
it("throws an error when given arguments", function() {
it('ignores configuration properties that are present but undefined', function() {
var initialConfig = {
random: true,
seed: '123',
failFast: true,
failSpecWithNoExpectations: true,
oneFailurePerSpec: true,
stopSpecOnExpectationFailure: true,
stopOnSpecFailure: true,
hideDisabled: true
};
env.configure(initialConfig);
env.configure({
random: undefined,
seed: undefined,
failFast: undefined,
failSpecWithNoExpectations: undefined,
oneFailurePerSpec: undefined,
stopSpecOnExpectationFailure: undefined,
stopOnSpecFailure: undefined,
hideDisabled: undefined
});
expect(env.configuration()).toEqual(
jasmine.objectContaining(initialConfig)
);
});
it('sets stopOnSpecFailure when failFast is set, and vice versa', function() {
env.configure({ failFast: true });
expect(env.configuration()).toEqual(
jasmine.objectContaining({
failFast: true,
stopOnSpecFailure: true
})
);
env.configure({ stopOnSpecFailure: false });
expect(env.configuration()).toEqual(
jasmine.objectContaining({
failFast: false,
stopOnSpecFailure: false
})
);
});
it('rejects a single call that sets stopOnSpecFailure and failFast to different values', function() {
expect(function() {
env.configure({ failFast: true, stopOnSpecFailure: false });
}).toThrowError(
'stopOnSpecFailure and failFast are aliases for each ' +
"other. Don't set failFast if you also set stopOnSpecFailure."
);
});
it('sets stopSpecOnExpectationFailure when oneFailurePerSpec is set, and vice versa', function() {
env.configure({ oneFailurePerSpec: true });
expect(env.configuration()).toEqual(
jasmine.objectContaining({
oneFailurePerSpec: true,
stopSpecOnExpectationFailure: true
})
);
env.configure({ stopSpecOnExpectationFailure: false });
expect(env.configuration()).toEqual(
jasmine.objectContaining({
oneFailurePerSpec: false,
stopSpecOnExpectationFailure: false
})
);
});
it('rejects a single call that sets stopSpecOnExpectationFailure and oneFailurePerSpec to different values', function() {
expect(function() {
env.configure({
oneFailurePerSpec: true,
stopSpecOnExpectationFailure: false
});
}).toThrowError(
'stopSpecOnExpectationFailure and oneFailurePerSpec are ' +
"aliases for each other. Don't set oneFailurePerSpec if you also set " +
'stopSpecOnExpectationFailure.'
);
});
describe('promise library', function() {
it('can be configured without a custom library', function() {
env.configure({});
env.configure({ Promise: undefined });
});
it('can be configured with a custom library', function() {
var myLibrary = {
resolve: jasmine.createSpy(),
reject: jasmine.createSpy()
};
env.configure({ Promise: myLibrary });
});
it('cannot be configured with an invalid promise library', function() {
var myLibrary = {};
expect(function() {
env.configure({ Promise: myLibrary });
}).toThrowError(
'Custom promise library missing `resolve`/`reject` functions'
);
});
});
it('defaults to multiple failures for specs', function() {
spyOn(jasmineUnderTest, 'Spec');
env.it('bar', function() {});
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
jasmine.objectContaining({
throwOnExpectationFailure: false
})
);
});
it('defaults to multiple failures for suites', function() {
spyOn(jasmineUnderTest, 'Suite');
env.describe('foo', function() {});
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(
jasmine.objectContaining({
throwOnExpectationFailure: false
})
);
});
describe('#describe', function() {
it('throws an error when given arguments', function() {
expect(function() {
env.describe('done method', function(done) {});
}).toThrowError('describe does not expect any arguments');
@@ -61,29 +207,41 @@ describe("Env", function() {
// anything other than a function throws an error.
expect(function() {
env.describe('undefined arg', undefined);
}).toThrowError(/describe expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/describe expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
expect(function() {
env.describe('null arg', null);
}).toThrowError(/describe expects a function argument; received \[object (Null|DOMWindow|Object)\]/);
}).toThrowError(
/describe expects a function argument; received \[object (Null|DOMWindow|Object)\]/
);
expect(function() {
env.describe('array arg', []);
}).toThrowError('describe expects a function argument; received [object Array]');
}).toThrowError(
'describe expects a function argument; received [object Array]'
);
expect(function() {
env.describe('object arg', {});
}).toThrowError('describe expects a function argument; received [object Object]');
}).toThrowError(
'describe expects a function argument; received [object Object]'
);
expect(function() {
env.describe('fn arg', function() {});
}).not.toThrowError('describe expects a function argument; received [object Function]');
}).not.toThrowError(
'describe expects a function argument; received [object Function]'
);
});
});
describe('#it', function () {
describe('#it', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.it('undefined arg', null);
}).toThrowError(/it expects a function argument; received \[object (Null|DOMWindow|Object)\]/);
}).toThrowError(
/it expects a function argument; received \[object (Null|DOMWindow|Object)\]/
);
});
it('does not throw when it is not given a fn argument', function() {
@@ -98,12 +256,30 @@ describe("Env", function() {
env.it('async', jasmine.getEnv().makeAsyncAwaitFunction());
}).not.toThrow();
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.it('huge timeout', function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('#xit', function() {
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
var excludeSpy = jasmine.createSpy();
spyOn(env, 'it').and.returnValue({
exclude: excludeSpy
});
env.xit('foo', function() {});
expect(excludeSpy).toHaveBeenCalledWith('Temporarily disabled with xit');
});
it('calls spec.pend with "Temporarily disabled with xit"', function() {
var pendSpy = jasmine.createSpy();
var realExclude = jasmineUnderTest.Spec.prototype.exclude;
spyOn(env, 'it').and.returnValue({
exclude: realExclude,
pend: pendSpy
});
env.xit('foo', function() {});
@@ -113,7 +289,9 @@ describe("Env", function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.xit('undefined arg', null);
}).toThrowError(/xit expects a function argument; received \[object (Null|DOMWindow|Object)\]/);
}).toThrowError(
/xit expects a function argument; received \[object (Null|DOMWindow|Object)\]/
);
});
it('does not throw when it is not given a fn argument', function() {
@@ -130,19 +308,29 @@ describe("Env", function() {
});
});
describe('#fit', function () {
describe('#fit', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.fit('undefined arg', undefined);
}).toThrowError(/fit expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/fit expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.fit('huge timeout', function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('#beforeEach', function () {
describe('#beforeEach', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.beforeEach(undefined);
}).toThrowError(/beforeEach expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/beforeEach expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
});
it('accepts an async function', function() {
@@ -151,13 +339,21 @@ describe("Env", function() {
env.beforeEach(jasmine.getEnv().makeAsyncAwaitFunction());
}).not.toThrow();
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.beforeEach(function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('#beforeAll', function () {
describe('#beforeAll', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.beforeAll(undefined);
}).toThrowError(/beforeAll expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/beforeAll expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
});
it('accepts an async function', function() {
@@ -166,13 +362,21 @@ describe("Env", function() {
env.beforeAll(jasmine.getEnv().makeAsyncAwaitFunction());
}).not.toThrow();
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.beforeAll(function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('#afterEach', function () {
describe('#afterEach', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.afterEach(undefined);
}).toThrowError(/afterEach expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/afterEach expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
});
it('accepts an async function', function() {
@@ -181,13 +385,21 @@ describe("Env", function() {
env.afterEach(jasmine.getEnv().makeAsyncAwaitFunction());
}).not.toThrow();
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.afterEach(function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('#afterAll', function () {
describe('#afterAll', function() {
it('throws an error when it receives a non-fn argument', function() {
expect(function() {
env.afterAll(undefined);
}).toThrowError(/afterAll expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/);
}).toThrowError(
/afterAll expects a function argument; received \[object (Undefined|DOMWindow|Object)\]/
);
});
it('accepts an async function', function() {
@@ -196,5 +408,143 @@ describe("Env", function() {
env.afterAll(jasmine.getEnv().makeAsyncAwaitFunction());
}).not.toThrow();
});
it('throws an error when the timeout value is too large for setTimeout', function() {
expect(function() {
env.afterAll(function() {}, 2147483648);
}).toThrowError('Timeout value cannot be greater than 2147483647');
});
});
describe('when not constructed with suppressLoadErrors: true', function() {
it('installs a global error handler on construction', function() {
var globalErrors = jasmine.createSpyObj('globalErrors', [
'install',
'uninstall',
'pushListener',
'popListener'
]);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env.cleanup_();
env = new jasmineUnderTest.Env();
expect(globalErrors.install).toHaveBeenCalled();
});
});
describe('when constructed with suppressLoadErrors: true', function() {
it('does not install a global error handler until execute is called', function() {
var globalErrors = jasmine.createSpyObj('globalErrors', [
'install',
'uninstall',
'pushListener',
'popListener'
]);
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
env.cleanup_();
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
expect(globalErrors.install).not.toHaveBeenCalled();
env.execute();
expect(globalErrors.install).toHaveBeenCalled();
});
});
it('creates an expectationFactory that uses the current custom equality testers and object formatters', function(done) {
function customEqualityTester() {}
function customObjectFormatter() {}
function prettyPrinter() {}
var RealSpec = jasmineUnderTest.Spec,
specInstance,
expectationFactory;
spyOn(jasmineUnderTest, 'MatchersUtil');
spyOn(jasmineUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
spyOn(jasmineUnderTest, 'Spec').and.callFake(function(options) {
expectationFactory = options.expectationFactory;
specInstance = new RealSpec(options);
return specInstance;
});
env.it('spec', function() {
env.addCustomEqualityTester(customEqualityTester);
env.addCustomObjectFormatter(customObjectFormatter);
expectationFactory('actual', specInstance);
});
env.execute(null, function() {
expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
customObjectFormatter
]);
expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({
customTesters: [customEqualityTester],
pp: prettyPrinter
});
done();
});
});
it('creates an asyncExpectationFactory that uses the current custom equality testers and object formatters', function(done) {
function customEqualityTester() {}
function customObjectFormatter() {}
function prettyPrinter() {}
var RealSpec = jasmineUnderTest.Spec,
specInstance,
asyncExpectationFactory;
spyOn(jasmineUnderTest, 'MatchersUtil');
spyOn(jasmineUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
spyOn(jasmineUnderTest, 'Spec').and.callFake(function(options) {
asyncExpectationFactory = options.asyncExpectationFactory;
specInstance = new RealSpec(options);
return specInstance;
});
env.it('spec', function() {
env.addCustomEqualityTester(customEqualityTester);
env.addCustomObjectFormatter(customObjectFormatter);
asyncExpectationFactory('actual', specInstance);
});
env.execute(null, function() {
expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
customObjectFormatter
]);
expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({
customTesters: [customEqualityTester],
pp: prettyPrinter
});
done();
});
});
describe('#execute', function() {
it('returns a promise when the environment supports promises', function() {
jasmine.getEnv().requirePromises();
expect(env.execute()).toBeInstanceOf(Promise);
});
it('returns a promise when a custom promise constructor is provided', function() {
function CustomPromise() {}
CustomPromise.resolve = function() {};
CustomPromise.reject = function() {};
env.configure({ Promise: CustomPromise });
expect(env.execute()).toBeInstanceOf(CustomPromise);
});
it('returns undefined when promises are unavailable', function() {
jasmine.getEnv().requireNoPromises();
expect(env.execute()).toBeUndefined();
});
it('should reset the topSuite when run twice', function() {
jasmine.getEnv().requirePromises();
spyOn(env.topSuite(), 'reset');
return env
.execute() // 1
.then(function() {
return env.execute(); // 2
})
.then(function() {
expect(env.topSuite().reset).toHaveBeenCalledOnceWith();
});
});
});
});

View File

@@ -1,5 +1,5 @@
describe("ExceptionFormatter", function() {
describe("#message", function() {
describe('ExceptionFormatter', function() {
describe('#message', function() {
it('formats Firefox exception messages', function() {
var sampleFirefoxException = {
fileName: 'foo.js',
@@ -10,7 +10,9 @@ describe("ExceptionFormatter", function() {
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(sampleFirefoxException);
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
expect(message).toEqual(
'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)'
);
});
it('formats Webkit exception messages', function() {
@@ -23,7 +25,9 @@ describe("ExceptionFormatter", function() {
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(sampleWebkitException);
expect(message).toEqual('A Classic Mistake: you got your foo in my bar in foo.js (line 1978)');
expect(message).toEqual(
'A Classic Mistake: you got your foo in my bar in foo.js (line 1978)'
);
});
it('formats V8 exception messages', function() {
@@ -37,27 +41,189 @@ describe("ExceptionFormatter", function() {
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
});
it("formats thrown exceptions that aren't errors", function() {
var thrown = "crazy error",
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(thrown);
it('formats unnamed exceptions with message', function() {
var unnamedError = { message: 'This is an unnamed error message.' };
expect(message).toEqual("crazy error thrown");
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(unnamedError);
expect(message).toEqual('This is an unnamed error message.');
});
it('formats empty exceptions with toString format', function() {
var EmptyError = function() {};
EmptyError.prototype.toString = function() {
return '[EmptyError]';
};
var emptyError = new EmptyError();
var exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(emptyError);
expect(message).toEqual('[EmptyError] thrown');
});
it("formats thrown exceptions that aren't errors", function() {
var thrown = 'crazy error',
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
message = exceptionFormatter.message(thrown);
expect(message).toEqual('crazy error thrown');
});
});
describe("#stack", function() {
it("formats stack traces from Webkit, Firefox, node.js or IE10+", function() {
if (jasmine.getEnv().ieVersion < 10 || jasmine.getEnv().safariVersion < 6) { return; }
describe('#stack', function() {
it('formats stack traces', function() {
var error;
try { throw new Error("an error") } catch(e) { error = e; }
try {
throw new Error('an error');
} catch (e) {
error = e;
}
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(/ExceptionFormatterSpec\.js.*\d+/)
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(
/ExceptionFormatterSpec\.js.*\d+/
);
});
it("returns null if no Error provided", function() {
it('filters Jasmine stack frames from V8-style traces but leaves unmatched lines intact', function() {
var error = {
message: 'nope',
stack:
'C:\\__spec__\\core\\UtilSpec.ts:120\n' +
" new Error('nope');\n" +
' ^\n' +
'\n' +
'Error: nope\n' +
' at fn1 (C:\\__spec__\\core\\UtilSpec.js:115:19)\n' +
' -> C:\\__spec__\\core\\UtilSpec.ts:120:15\n' +
' at fn2 (C:\\__jasmine__\\lib\\jasmine-core\\jasmine.js:7533:40)\n' +
' at fn3 (C:\\__jasmine__\\lib\\jasmine-core\\jasmine.js:7575:25)\n' +
' at fn4 (node:internal/timers:462:21)\n'
};
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: 'C:\\__jasmine__\\lib\\jasmine-core\\jasmine.js'
});
var result = subject.stack(error);
expect(result).toEqual(
'C:\\__spec__\\core\\UtilSpec.ts:120\n' +
" new Error('nope');\n" +
' ^\n' +
'Error: nope\n' +
' at fn1 (C:\\__spec__\\core\\UtilSpec.js:115:19)\n' +
' -> C:\\__spec__\\core\\UtilSpec.ts:120:15\n' +
' at <Jasmine>\n' +
' at fn4 (node:internal/timers:462:21)'
);
});
it('filters Jasmine stack frames from V8 style traces', function() {
var error = {
message: 'nope',
stack:
'Error: nope\n' +
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at fn2 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
};
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
});
var result = subject.stack(error);
expect(result).toEqual(
'Error: nope\n' +
' at fn1 (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at <Jasmine>\n' +
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)'
);
});
it('filters Jasmine stack frames from Webkit style traces', function() {
var error = {
stack:
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
};
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
});
var result = subject.stack(error);
expect(result).toEqual(
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'<Jasmine>\n' +
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
);
});
it('filters Jasmine stack frames in this environment', function() {
var error, i;
try {
throw new Error('an error');
} catch (e) {
error = e;
}
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: jasmine.util.jasmineFile()
});
var result = subject.stack(error);
var lines = result.split('\n');
if (lines[0].match(/an error/)) {
lines.shift();
}
expect(lines[0]).toMatch(/ExceptionFormatterSpec.js/);
expect(lines[1]).toMatch(/<Jasmine>/);
// Node has some number of additional frames below Jasmine.
for (i = 2; i < lines.length; i++) {
expect(lines[i]).not.toMatch(/jasmine.js/);
}
});
it('handles multiline error messages in this environment', function() {
var error,
msg = 'an error\nwith two lines';
try {
throw new Error(msg);
} catch (e) {
error = e;
}
if (error.stack.indexOf(msg) === -1) {
pending("Stack traces don't have messages in this environment");
}
var subject = new jasmineUnderTest.ExceptionFormatter({
jasmineFile: jasmine.util.jasmineFile()
});
var result = subject.stack(error);
var lines = result.split('\n');
expect(lines[0]).toMatch(/an error/);
expect(lines[1]).toMatch(/with two lines/);
expect(lines[2]).toMatch(/ExceptionFormatterSpec.js/);
expect(lines[3]).toMatch(/<Jasmine>/);
});
it('returns null if no Error provided', function() {
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
});
it('includes error properties in stack', function() {
var error;
try {
throw new Error('an error');
} catch (e) {
error = e;
}
error.someProperty = 'hello there';
var result = new jasmineUnderTest.ExceptionFormatter().stack(error);
expect(result).toMatch(/error properties:.*someProperty.*hello there/);
});
});
});

View File

@@ -5,64 +5,49 @@ describe('Exceptions:', function() {
env = new jasmineUnderTest.Env();
});
describe('with break on exception', function() {
it('should not catch the exception', function() {
env.catchExceptions(false);
env.describe('suite for break on exceptions', function() {
env.it('should break when an exception is thrown', function() {
throw new Error('I should hit a breakpoint!');
});
});
var spy = jasmine.createSpy('spy');
try {
env.execute();
spy();
}
catch (e) {}
expect(spy).not.toHaveBeenCalled();
});
afterEach(function() {
env.cleanup_();
});
describe("with catch on exception", function() {
it('should handle exceptions thrown, but continue', function(done) {
var secondTest = jasmine.createSpy('second test');
env.describe('Suite for handles exceptions', function () {
env.it('should be a test that fails because it throws an exception', function() {
it('should handle exceptions thrown, but continue', function(done) {
var secondTest = jasmine.createSpy('second test');
env.describe('Suite for handles exceptions', function() {
env.it(
'should be a test that fails because it throws an exception',
function() {
throw new Error();
});
env.it('should be a passing test that runs after exceptions are thrown from a async test', secondTest);
});
var expectations = function() {
expect(secondTest).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: expectations });
env.execute();
}
);
env.it(
'should be a passing test that runs after exceptions are thrown from a async test',
secondTest
);
});
it("should handle exceptions thrown directly in top-level describe blocks and continue", function(done) {
var secondDescribe = jasmine.createSpy("second describe");
env.describe("a suite that throws an exception", function () {
env.it("is a test that should pass", function () {
this.expect(true).toEqual(true);
});
var expectations = function() {
expect(secondTest).toHaveBeenCalled();
done();
};
throw new Error("top level error");
env.execute(null, expectations);
});
it('should handle exceptions thrown directly in top-level describe blocks and continue', function(done) {
var secondDescribe = jasmine.createSpy('second describe');
env.describe('a suite that throws an exception', function() {
env.it('is a test that should pass', function() {
this.expect(true).toEqual(true);
});
env.describe("a suite that doesn't throw an exception", secondDescribe);
var expectations = function() {
expect(secondDescribe).toHaveBeenCalled();
done();
};
env.addReporter({ jasmineDone: expectations });
env.execute();
throw new Error('top level error');
});
env.describe("a suite that doesn't throw an exception", secondDescribe);
var expectations = function() {
expect(secondDescribe).toHaveBeenCalled();
done();
};
env.execute(null, expectations);
});
});

View File

@@ -0,0 +1,123 @@
describe('ExpectationFilterChain', function() {
describe('#addFilter', function() {
it('returns a new filter chain with the added filter', function() {
var first = jasmine.createSpy('first'),
second = jasmine.createSpy('second'),
orig = new jasmineUnderTest.ExpectationFilterChain({
modifyFailureMessage: first
}),
added = orig.addFilter({ selectComparisonFunc: second });
added.modifyFailureMessage();
expect(first).toHaveBeenCalled();
added.selectComparisonFunc();
expect(second).toHaveBeenCalled();
});
it('does not modify the original filter chain', function() {
var orig = new jasmineUnderTest.ExpectationFilterChain({}),
f = jasmine.createSpy('f');
orig.addFilter({ selectComparisonFunc: f });
orig.selectComparisonFunc();
expect(f).not.toHaveBeenCalled();
});
});
describe('#selectComparisonFunc', function() {
describe('When no filters have #selectComparisonFunc', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.selectComparisonFunc()).toBeUndefined();
});
});
describe('When some filters have #selectComparisonFunc', function() {
it('calls the first filter that has #selectComparisonFunc', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({ selectComparisonFunc: first })
.addFilter({ selectComparisonFunc: second }),
matcher = {},
result;
result = chain.selectComparisonFunc(matcher);
expect(first).toHaveBeenCalledWith(matcher);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#buildFailureMessage', function() {
describe('When no filters have #buildFailureMessage', function() {
it('returns undefined', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.buildFailureMessage()).toBeUndefined();
});
});
describe('When some filters have #buildFailureMessage', function() {
it('calls the first filter that has #buildFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({ buildFailureMessage: first })
.addFilter({ buildFailureMessage: second }),
matcherResult = { pass: false },
matcherName = 'foo',
args = [],
matchersUtil = {},
result;
result = chain.buildFailureMessage(
matcherResult,
matcherName,
args,
matchersUtil
);
expect(first).toHaveBeenCalledWith(
matcherResult,
matcherName,
args,
matchersUtil
);
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
describe('#modifyFailureMessage', function() {
describe('When no filters have #modifyFailureMessage', function() {
it('returns the original message', function() {
var chain = new jasmineUnderTest.ExpectationFilterChain();
chain.addFilter({});
expect(chain.modifyFailureMessage('msg')).toEqual('msg');
});
});
describe('When some filters have #modifyFailureMessage', function() {
it('calls the first filter that has #modifyFailureMessage', function() {
var first = jasmine.createSpy('first').and.returnValue('first'),
second = jasmine.createSpy('second').and.returnValue('second'),
chain = new jasmineUnderTest.ExpectationFilterChain()
.addFilter({ modifyFailureMessage: first })
.addFilter({ modifyFailureMessage: second }),
result;
result = chain.modifyFailureMessage('original');
expect(first).toHaveBeenCalledWith('original');
expect(second).not.toHaveBeenCalled();
expect(result).toEqual('first');
});
});
});
});

View File

@@ -1,61 +1,126 @@
describe("buildExpectationResult", function() {
it("defaults to passed", function() {
var result = jasmineUnderTest.buildExpectationResult({passed: 'some-value'});
describe('buildExpectationResult', function() {
it('defaults to passed', function() {
var result = jasmineUnderTest.buildExpectationResult({
passed: 'some-value'
});
expect(result.passed).toBe('some-value');
});
it("message defaults to Passed for passing specs", function() {
var result = jasmineUnderTest.buildExpectationResult({passed: true, message: 'some-value'});
it('message defaults to Passed for passing specs', function() {
var result = jasmineUnderTest.buildExpectationResult({
passed: true,
message: 'some-value'
});
expect(result.message).toBe('Passed.');
});
it("message returns the message for failing expectations", function() {
var result = jasmineUnderTest.buildExpectationResult({passed: false, message: 'some-value'});
it('message returns the message for failing expectations', function() {
var result = jasmineUnderTest.buildExpectationResult({
passed: false,
message: 'some-value'
});
expect(result.message).toBe('some-value');
});
it("delegates message formatting to the provided formatter if there was an Error", function() {
var fakeError = {message: 'foo'},
messageFormatter = jasmine.createSpy("exception message formatter").and.returnValue(fakeError.message);
it('delegates message formatting to the provided formatter if there was an Error', function() {
var fakeError = { message: 'foo' },
messageFormatter = jasmine
.createSpy('exception message formatter')
.and.returnValue(fakeError.message);
var result = jasmineUnderTest.buildExpectationResult(
{
passed: false,
error: fakeError,
messageFormatter: messageFormatter
});
var result = jasmineUnderTest.buildExpectationResult({
passed: false,
error: fakeError,
messageFormatter: messageFormatter
});
expect(messageFormatter).toHaveBeenCalledWith(fakeError);
expect(result.message).toEqual('foo');
});
it("delegates stack formatting to the provided formatter if there was an Error", function() {
var fakeError = {stack: 'foo'},
stackFormatter = jasmine.createSpy("stack formatter").and.returnValue(fakeError.stack);
it('delegates stack formatting to the provided formatter if there was an Error', function() {
var fakeError = { stack: 'foo' },
stackFormatter = jasmine
.createSpy('stack formatter')
.and.returnValue(fakeError.stack);
var result = jasmineUnderTest.buildExpectationResult(
{
passed: false,
error: fakeError,
stackFormatter: stackFormatter
});
var result = jasmineUnderTest.buildExpectationResult({
passed: false,
error: fakeError,
stackFormatter: stackFormatter
});
expect(stackFormatter).toHaveBeenCalledWith(fakeError);
expect(result.stack).toEqual('foo');
});
it("matcherName returns passed matcherName", function() {
var result = jasmineUnderTest.buildExpectationResult({matcherName: 'some-value'});
it('delegates stack formatting to the provided formatter if there was a provided errorForStack', function() {
var fakeError = { stack: 'foo' },
stackFormatter = jasmine
.createSpy('stack formatter')
.and.returnValue(fakeError.stack);
var result = jasmineUnderTest.buildExpectationResult({
passed: false,
errorForStack: fakeError,
stackFormatter: stackFormatter
});
expect(stackFormatter).toHaveBeenCalledWith(fakeError);
expect(result.stack).toEqual('foo');
});
it('matcherName returns passed matcherName', function() {
var result = jasmineUnderTest.buildExpectationResult({
matcherName: 'some-value'
});
expect(result.matcherName).toBe('some-value');
});
it("expected returns passed expected", function() {
var result = jasmineUnderTest.buildExpectationResult({expected: 'some-value'});
it('expected returns passed expected', function() {
var result = jasmineUnderTest.buildExpectationResult({
expected: 'some-value'
});
expect(result.expected).toBe('some-value');
});
it("actual returns passed actual", function() {
var result = jasmineUnderTest.buildExpectationResult({actual: 'some-value'});
it('actual returns passed actual', function() {
var result = jasmineUnderTest.buildExpectationResult({
actual: 'some-value'
});
expect(result.actual).toBe('some-value');
});
it('handles nodejs assertions', function() {
if (typeof require === 'undefined') {
return;
}
var assert = require('assert');
var error;
var value = 8421;
var expectedValue = 'JasmineExpectationTestValue';
try {
assert.equal(value, expectedValue);
} catch (e) {
error = e;
}
expect(error.code).toEqual('ERR_ASSERTION');
expect(error.actual).toEqual(value);
expect(error.expected).toEqual(expectedValue);
expect(error.operator).toEqual('==');
var result = jasmineUnderTest.buildExpectationResult({
passed: false,
matcherName: '',
expected: '',
actual: '',
error: error
});
expect(result.code).toEqual('ERR_ASSERTION');
expect(result.actual).toEqual(value);
expect(result.expected).toEqual(expectedValue);
expect(result.matcherName).toEqual('assert ==');
});
});

View File

@@ -1,12 +1,12 @@
describe("Expectation", function() {
it("makes custom matchers available to this expectation", function() {
describe('Expectation', function() {
it('makes custom matchers available to this expectation', function() {
var matchers = {
toFoo: function() {},
toBar: function() {}
},
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers
});
@@ -14,7 +14,7 @@ describe("Expectation", function() {
expect(expectation.toBar).toBeDefined();
});
it(".addCoreMatchers makes matchers available to any expectation", function() {
it('.addCoreMatchers makes matchers available to any expectation', function() {
var coreMatchers = {
toQuux: function() {}
},
@@ -22,45 +22,48 @@ describe("Expectation", function() {
jasmineUnderTest.Expectation.addCoreMatchers(coreMatchers);
expectation = new jasmineUnderTest.Expectation({});
expectation = jasmineUnderTest.Expectation.factory({});
expect(expectation.toQuux).toBeDefined();
});
it("Factory builds an expectation/negative expectation", function() {
var builtExpectation = jasmineUnderTest.Expectation.Factory();
expect(builtExpectation instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not instanceof jasmineUnderTest.Expectation).toBe(true);
expect(builtExpectation.not.isNot).toBe(true);
});
it("wraps matchers's compare functions, passing in matcher dependencies", function() {
var fakeCompare = function() { return { pass: true }; },
matcherFactory = jasmine.createSpy("matcher").and.returnValue({ compare: fakeCompare }),
var fakeCompare = function() {
return { pass: true };
},
matcherFactory = jasmine
.createSpy('matcher')
.and.returnValue({ compare: fakeCompare }),
matchers = {
toFoo: matcherFactory
},
util = {},
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
customEqualityTesters = ['a'],
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
util: util,
expectation = jasmineUnderTest.Expectation.factory({
matchersUtil: matchersUtil,
customMatchers: matchers,
customEqualityTesters: customEqualityTesters,
actual: "an actual",
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(matcherFactory).toHaveBeenCalledWith(util, customEqualityTesters)
expect(matcherFactory).toHaveBeenCalledWith(
matchersUtil,
customEqualityTesters
);
});
it("wraps matchers's compare functions, passing the actual and expected", function() {
var fakeCompare = jasmine.createSpy('fake-compare').and.returnValue({pass: true}),
var fakeCompare = jasmine
.createSpy('fake-compare')
.and.returnValue({ pass: true }),
matchers = {
toFoo: function() {
return {
@@ -68,260 +71,275 @@ describe("Expectation", function() {
};
}
},
util = {
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
util: util,
expectation = jasmineUnderTest.Expectation.factory({
matchersUtil: matchersUtil,
customMatchers: matchers,
actual: "an actual",
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(fakeCompare).toHaveBeenCalledWith("an actual", "hello");
expect(fakeCompare).toHaveBeenCalledWith('an actual', 'hello');
});
it("reports a passing result to the spec when the comparison passes", function() {
it('reports a passing result to the spec when the comparison passes', function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
compare: function() {
return { pass: true };
}
};
}
},
util = {
matchersUtil = {
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
matchersUtil: matchersUtil,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: true,
message: "",
message: '',
error: undefined,
expected: "hello",
actual: "an actual"
expected: 'hello',
actual: 'an actual',
errorForStack: undefined
});
});
it("reports a failing result to the spec when the comparison fails", function() {
it('reports a failing result to the spec when the comparison fails', function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
compare: function() {
return { pass: false };
}
};
}
},
util = {
buildFailureMessage: function() { return ""; }
matchersUtil = {
buildFailureMessage: function() {
return '';
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
util: util,
actual: "an actual",
matchersUtil: matchersUtil,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
actual: "an actual",
message: "",
error: undefined
expected: 'hello',
actual: 'an actual',
message: '',
error: undefined,
errorForStack: undefined
});
});
it("reports a failing result and a custom fail message to the spec when the comparison fails", function() {
it('reports a failing result and a custom fail message to the spec when the comparison fails', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: "I am a custom message"
message: 'I am a custom message'
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
actual: "an actual",
expectation = jasmineUnderTest.Expectation.factory({
actual: 'an actual',
customMatchers: matchers,
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: undefined
});
});
it("reports a failing result with a custom fail message function to the spec when the comparison fails", function() {
it('reports a failing result with a custom fail message function to the spec when the comparison fails', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: function() { return "I am a custom message"; }
message: function() {
return 'I am a custom message';
}
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: undefined
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: undefined,
errorForStack: undefined
});
});
it("reports a passing result to the spec when the comparison fails for a negative expectation", function() {
it('reports a passing result to the spec when the comparison fails for a negative expectation', function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: false }; }
compare: function() {
return { pass: false };
}
};
}
},
util = {
buildFailureMessage: function() { return ""; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: true,
message: "",
message: '',
error: undefined,
expected: "hello",
actual: actual
});
});
it("reports a failing result to the spec when the comparison passes for a negative expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; }
};
}
},
util = {
buildFailureMessage: function() { return "default message"; }
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
expectation;
expectation = new jasmineUnderTest.Expectation({
customMatchers: matchers,
actual: "an actual",
util: util,
addExpectationResult: addExpectationResult,
isNot: true
});
expectation.toFoo("hello");
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
passed: false,
expected: "hello",
expected: 'hello',
actual: actual,
message: "default message",
error: undefined
errorForStack: undefined
});
});
it("reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation", function() {
it('reports a failing result to the spec when the comparison passes for a negative expectation', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return { pass: true };
}
};
}
},
matchersUtil = {
buildFailureMessage: function() {
return 'default message';
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
expectation;
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: 'an actual',
matchersUtil: matchersUtil,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: actual,
message: 'default message',
error: undefined,
errorForStack: undefined
});
});
it('reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: "I am a custom message"
message: 'I am a custom message'
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
expected: 'hello',
actual: actual,
message: "I am a custom message",
error: undefined
message: 'I am a custom message',
error: undefined,
errorForStack: undefined
});
});
@@ -329,31 +347,35 @@ describe("Expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
negativeCompare: function() { return { pass: true }; }
compare: function() {
return { pass: true };
},
negativeCompare: function() {
return { pass: true };
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(true, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: true,
expected: "hello",
expected: 'hello',
actual: actual,
message: "",
error: undefined
message: '',
error: undefined,
errorForStack: undefined
});
});
@@ -361,7 +383,9 @@ describe("Expectation", function() {
var matchers = {
toFoo: function() {
return {
compare: function() { return { pass: true }; },
compare: function() {
return { pass: true };
},
negativeCompare: function() {
return {
pass: false,
@@ -371,64 +395,322 @@ describe("Expectation", function() {
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
actual = "an actual",
addExpectationResult = jasmine.createSpy('addExpectationResult'),
actual = 'an actual',
expectation;
expectation = new jasmineUnderTest.Expectation({
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: "an actual",
addExpectationResult: addExpectationResult,
isNot: true
});
actual: 'an actual',
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
expected: 'hello',
actual: actual,
message: "I'm a custom message",
error: undefined
error: undefined,
errorForStack: undefined
});
});
it("reports a custom error message to the spec", function() {
var customError = new Error("I am a custom error");
it('reports a custom error message to the spec', function() {
var customError = new Error('I am a custom error');
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: "I am a custom message",
message: 'I am a custom message',
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy("addExpectationResult"),
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = new jasmineUnderTest.Expectation({
actual: "an actual",
expectation = jasmineUnderTest.Expectation.factory({
actual: 'an actual',
customMatchers: matchers,
addExpectationResult: addExpectationResult
});
expectation.toFoo("hello");
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: "toFoo",
matcherName: 'toFoo',
passed: false,
expected: "hello",
actual: "an actual",
message: "I am a custom message",
error: customError
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: customError,
errorForStack: undefined
});
});
});
it("reports a custom message to the spec when a 'not' comparison fails", function() {
var customError = new Error('I am a custom error');
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: 'I am a custom message',
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: 'an actual',
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: customError,
errorForStack: undefined
});
});
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
var customError = new Error('I am a custom error');
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() {
return 'I am a custom message';
},
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation;
expectation = jasmineUnderTest.Expectation.factory({
actual: 'an actual',
customMatchers: matchers,
addExpectationResult: addExpectationResult
}).not;
expectation.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(false, {
matcherName: 'toFoo',
passed: false,
expected: 'hello',
actual: 'an actual',
message: 'I am a custom message',
error: customError,
errorForStack: undefined
});
});
describe('#withContext', function() {
it('prepends the context to the generated failure message', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return { pass: false };
}
};
}
},
matchersUtil = {
buildFailureMessage: function() {
return 'failure message';
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
matchersUtil: matchersUtil,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.withContext('Some context').toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: 'Some context: failure message'
})
);
});
it('prepends the context to a custom failure message', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return { pass: false, message: 'msg' };
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.withContext('Some context').toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: 'Some context: msg'
})
);
});
it('indents a multiline failure message', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return { pass: false, message: 'a\nmultiline\nmessage' };
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
}),
actualMessage;
expectation.withContext('Some context').toFoo('hello');
actualMessage = addExpectationResult.calls.argsFor(0)[1].message;
expect(actualMessage).toEqual(
'Some context:\n a\n multiline\n message'
);
});
it('prepends the context to a custom failure message from a function', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: false,
message: function() {
return 'msg';
}
};
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.withContext('Some context').toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: 'Some context: msg'
})
);
});
it('works with #not', function() {
var matchers = {
toFoo: function() {
return {
compare: function() {
return { pass: true };
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
pp = jasmineUnderTest.makePrettyPrinter(),
expectation = jasmineUnderTest.Expectation.factory({
customMatchers: matchers,
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp }),
actual: 'an actual',
addExpectationResult: addExpectationResult
});
expectation.withContext('Some context').not.toFoo();
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: "Some context: Expected 'an actual' not to foo."
})
);
});
it('works with #not and a custom message', function() {
var customError = new Error('I am a custom error');
var matchers = {
toFoo: function() {
return {
compare: function() {
return {
pass: true,
message: function() {
return 'I am a custom message';
},
error: customError
};
}
};
}
},
addExpectationResult = jasmine.createSpy('addExpectationResult'),
expectation = jasmineUnderTest.Expectation.factory({
actual: 'an actual',
customMatchers: matchers,
addExpectationResult: addExpectationResult
});
expectation.withContext('Some context').not.toFoo('hello');
expect(addExpectationResult).toHaveBeenCalledWith(
false,
jasmine.objectContaining({
message: 'Some context: I am a custom message'
})
);
});
});
});

View File

@@ -1,8 +1,8 @@
describe("GlobalErrors", function() {
it("calls the added handler on error", function() {
describe('GlobalErrors', function() {
it('calls the added handler on error', function() {
var fakeGlobal = { onerror: null },
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
@@ -12,11 +12,48 @@ describe("GlobalErrors", function() {
expect(handler).toHaveBeenCalledWith('foo');
});
it("only calls the most recent handler", function() {
it('enables external interception of error by overriding global.onerror', function() {
var fakeGlobal = { onerror: null },
handler1 = jasmine.createSpy('errorHandler1'),
handler2 = jasmine.createSpy('errorHandler2'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
handler = jasmine.createSpy('errorHandler'),
hijackHandler = jasmine.createSpy('hijackErrorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
fakeGlobal.onerror = hijackHandler;
fakeGlobal.onerror('foo');
expect(hijackHandler).toHaveBeenCalledWith('foo');
expect(handler).not.toHaveBeenCalled();
});
it('calls the global error handler with all parameters', function() {
var fakeGlobal = { onerror: null },
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
fooError = new Error('foo');
errors.install();
errors.pushListener(handler);
fakeGlobal.onerror(fooError.message, 'foo.js', 1, 1, fooError);
expect(handler).toHaveBeenCalledWith(
fooError.message,
'foo.js',
1,
1,
fooError
);
});
it('only calls the most recent handler', function() {
var fakeGlobal = { onerror: null },
handler1 = jasmine.createSpy('errorHandler1'),
handler2 = jasmine.createSpy('errorHandler2'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler1);
@@ -28,17 +65,17 @@ describe("GlobalErrors", function() {
expect(handler2).toHaveBeenCalledWith('foo');
});
it("calls previous handlers when one is removed", function() {
it('calls previous handlers when one is removed', function() {
var fakeGlobal = { onerror: null },
handler1 = jasmine.createSpy('errorHandler1'),
handler2 = jasmine.createSpy('errorHandler2'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
handler1 = jasmine.createSpy('errorHandler1'),
handler2 = jasmine.createSpy('errorHandler2'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler1);
errors.pushListener(handler2);
errors.popListener();
errors.popListener(handler2);
fakeGlobal.onerror('foo');
@@ -46,10 +83,17 @@ describe("GlobalErrors", function() {
expect(handler2).not.toHaveBeenCalled();
});
it("uninstalls itself, putting back a previous callback", function() {
it('throws when no listener is passed to #popListener', function() {
var errors = new jasmineUnderTest.GlobalErrors({});
expect(function() {
errors.popListener();
}).toThrowError('popListener expects a listener');
});
it('uninstalls itself, putting back a previous callback', function() {
var originalCallback = jasmine.createSpy('error'),
fakeGlobal = { onerror: originalCallback },
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
fakeGlobal = { onerror: originalCallback },
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
expect(fakeGlobal.onerror).toBe(originalCallback);
@@ -62,10 +106,10 @@ describe("GlobalErrors", function() {
expect(fakeGlobal.onerror).toBe(originalCallback);
});
it("rethrows the original error when there is no handler", function() {
var fakeGlobal = { },
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
originalError = new Error('nope');
it('rethrows the original error when there is no handler', function() {
var fakeGlobal = {},
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal),
originalError = new Error('nope');
errors.install();
@@ -78,22 +122,31 @@ describe("GlobalErrors", function() {
errors.uninstall();
});
it("works in node.js", function() {
it('reports uncaught exceptions in node.js', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: jasmine.createSpy('process.removeListener'),
listeners: jasmine.createSpy('process.listeners').and.returnValue(['foo']),
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
process: {
on: jasmine.createSpy('process.on'),
removeListener: jasmine.createSpy('process.removeListener'),
listeners: jasmine
.createSpy('process.listeners')
.and.returnValue(['foo']),
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', jasmine.any(Function));
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith('uncaughtException');
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith('uncaughtException');
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'uncaughtException',
jasmine.any(Function)
);
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
'uncaughtException'
);
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
'uncaughtException'
);
errors.pushListener(handler);
@@ -101,10 +154,268 @@ describe("GlobalErrors", function() {
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
'Uncaught exception: Error: bar'
);
errors.uninstall();
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith('uncaughtException', addedListener);
expect(fakeGlobal.process.on).toHaveBeenCalledWith('uncaughtException', 'foo');
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
'uncaughtException',
addedListener
);
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'uncaughtException',
'foo'
);
});
describe('Reporting unhandled promise rejections in node.js', function() {
it('reports rejections with `Error` reasons', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: jasmine.createSpy('process.removeListener'),
listeners: jasmine
.createSpy('process.listeners')
.and.returnValue(['foo']),
removeAllListeners: jasmine.createSpy('process.removeAllListeners')
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
jasmine.any(Function)
);
expect(fakeGlobal.process.listeners).toHaveBeenCalledWith(
'unhandledRejection'
);
expect(fakeGlobal.process.removeAllListeners).toHaveBeenCalledWith(
'unhandledRejection'
);
errors.pushListener(handler);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(new Error('bar'));
expect(handler).toHaveBeenCalledWith(new Error('bar'));
expect(handler.calls.argsFor(0)[0].jasmineMessage).toBe(
'Unhandled promise rejection: Error: bar'
);
errors.uninstall();
expect(fakeGlobal.process.removeListener).toHaveBeenCalledWith(
'unhandledRejection',
addedListener
);
expect(fakeGlobal.process.on).toHaveBeenCalledWith(
'unhandledRejection',
'foo'
);
});
it('reports rejections with non-`Error` reasons', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: function() {},
listeners: function() {
return [];
},
removeAllListeners: function() {}
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
'unhandledRejection'
);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(17);
expect(handler).toHaveBeenCalledWith(
new Error(
'Unhandled promise rejection: 17\n' +
'(Tip: to get a useful stack trace, use ' +
'Promise.reject(new Error(...)) instead of Promise.reject(...).)'
)
);
});
it('reports rejections with no reason provided', function() {
var fakeGlobal = {
process: {
on: jasmine.createSpy('process.on'),
removeListener: function() {},
listeners: function() {
return [];
},
removeAllListeners: function() {}
}
},
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
expect(fakeGlobal.process.on.calls.argsFor(1)[0]).toEqual(
'unhandledRejection'
);
var addedListener = fakeGlobal.process.on.calls.argsFor(1)[1];
addedListener(undefined);
expect(handler).toHaveBeenCalledWith(
new Error(
'Unhandled promise rejection with no error or message\n' +
'(Tip: to get a useful stack trace, use ' +
'Promise.reject(new Error(...)) instead of Promise.reject().)'
)
);
});
});
describe('Reporting unhandled promise rejections in the browser', function() {
it('subscribes and unsubscribes from the unhandledrejection event', function() {
var fakeGlobal = jasmine.createSpyObj('globalErrors', [
'addEventListener',
'removeEventListener',
'onerror'
]),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
expect(fakeGlobal.addEventListener).toHaveBeenCalledWith(
'unhandledrejection',
jasmine.any(Function)
);
var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1];
errors.uninstall();
expect(fakeGlobal.removeEventListener).toHaveBeenCalledWith(
'unhandledrejection',
addedListener
);
});
it('reports rejections whose reason is a string', function() {
var fakeGlobal = jasmine.createSpyObj('globalErrors', [
'addEventListener',
'removeEventListener',
'onerror'
]),
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1];
addedListener({ reason: 'nope' });
expect(handler).toHaveBeenCalledWith('Unhandled promise rejection: nope');
});
it('reports rejections whose reason is an Error', function() {
var fakeGlobal = jasmine.createSpyObj('globalErrors', [
'addEventListener',
'removeEventListener',
'onerror'
]),
handler = jasmine.createSpy('errorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1];
var reason;
try {
// Throwing ensures that we get a stack property in all browsers
throw new Error('bar');
} catch (e) {
reason = e;
}
addedListener({ reason: reason });
expect(handler).toHaveBeenCalledWith(
jasmine.objectContaining({
jasmineMessage: 'Unhandled promise rejection: Error: bar',
message: reason.message,
stack: reason.stack
})
);
});
describe('Enabling external interception of reported rejections by overriding global.onerror', function() {
it('overriding global.onerror intercepts rejections whose reason is a string', function() {
var fakeGlobal = jasmine.createSpyObj('globalErrors', [
'addEventListener'
]),
handler = jasmine.createSpy('errorHandler'),
hijackHandler = jasmine.createSpy('hijackErrorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
fakeGlobal.onerror = hijackHandler;
var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1];
addedListener({ reason: 'nope' });
expect(hijackHandler).toHaveBeenCalledWith(
'Unhandled promise rejection: nope'
);
expect(handler).not.toHaveBeenCalled();
});
it('overriding global.onerror intercepts rejections whose reason is an Error', function() {
var fakeGlobal = jasmine.createSpyObj('globalErrors', [
'addEventListener'
]),
handler = jasmine.createSpy('errorHandler'),
hijackHandler = jasmine.createSpy('hijackErrorHandler'),
errors = new jasmineUnderTest.GlobalErrors(fakeGlobal);
errors.install();
errors.pushListener(handler);
fakeGlobal.onerror = hijackHandler;
var addedListener = fakeGlobal.addEventListener.calls.argsFor(0)[1];
var reason;
try {
// Throwing ensures that we get a stack property in all browsers
throw new Error('bar');
} catch (e) {
reason = e;
}
addedListener({ reason: reason });
expect(hijackHandler).toHaveBeenCalledWith(
jasmine.objectContaining({
jasmineMessage: 'Unhandled promise rejection: Error: bar',
message: reason.message,
stack: reason.stack
})
);
expect(handler).not.toHaveBeenCalled();
});
});
});
});

View File

@@ -1,87 +1,5 @@
xdescribe('JsApiReporter (integration specs)', function() {
describe('results', function() {
var reporter, spec1, spec2;
var env;
var suite, nestedSuite, nestedSpec;
beforeEach(function() {
env = new jasmineUnderTest.Env();
suite = env.describe("top-level suite", function() {
spec1 = env.it("spec 1", function() {
this.expect(true).toEqual(true);
});
spec2 = env.it("spec 2", function() {
this.expect(true).toEqual(false);
});
nestedSuite = env.describe("nested suite", function() {
nestedSpec = env.it("nested spec", function() {
expect(true).toEqual(true);
});
});
});
reporter = new jasmineUnderTest.JsApiReporter({});
env.addReporter(reporter);
env.execute();
});
it('results() should return a hash of all results, indexed by spec id', function() {
var expectedSpec1Results = {
result: "passed"
},
expectedSpec2Results = {
result: "failed"
};
expect(reporter.results()[spec1.id].result).toEqual('passed');
expect(reporter.results()[spec2.id].result).toEqual('failed');
});
it("should return nested suites as children of their parents", function() {
expect(reporter.suites()).toEqual([
{ id: 0, name: 'top-level suite', type: 'suite',
children: [
{ id: 0, name: 'spec 1', type: 'spec', children: [ ] },
{ id: 1, name: 'spec 2', type: 'spec', children: [ ] },
{ id: 1, name: 'nested suite', type: 'suite',
children: [
{ id: 2, name: 'nested spec', type: 'spec', children: [ ] }
]
},
]
}
]);
});
describe("#summarizeResult_", function() {
it("should summarize a passing result", function() {
var result = reporter.results()[spec1.id];
var summarizedResult = reporter.summarizeResult_(result);
expect(summarizedResult.result).toEqual('passed');
expect(summarizedResult.messages.length).toEqual(0);
});
it("should have a stack trace for failing specs", function() {
var result = reporter.results()[spec2.id];
var summarizedResult = reporter.summarizeResult_(result);
expect(summarizedResult.result).toEqual('failed');
expect(summarizedResult.messages[0].trace.stack).toEqual(result.messages[0].trace.stack);
});
});
});
});
describe("JsApiReporter", function() {
it("knows when a full environment is started", function() {
describe('JsApiReporter', function() {
it('knows when a full environment is started', function() {
var reporter = new jasmineUnderTest.JsApiReporter({});
expect(reporter.started).toBe(false);
@@ -93,7 +11,7 @@ describe("JsApiReporter", function() {
expect(reporter.finished).toBe(false);
});
it("knows when a full environment is done", function() {
it('knows when a full environment is done', function() {
var reporter = new jasmineUnderTest.JsApiReporter({});
expect(reporter.started).toBe(false);
@@ -127,58 +45,60 @@ describe("JsApiReporter", function() {
expect(reporter.status()).toEqual('done');
});
it("tracks a suite", function() {
it('tracks a suite', function() {
var reporter = new jasmineUnderTest.JsApiReporter({});
reporter.suiteStarted({
id: 123,
description: "A suite"
description: 'A suite'
});
var suites = reporter.suites();
expect(suites).toEqual({123: {id: 123, description: "A suite"}});
expect(suites).toEqual({ 123: { id: 123, description: 'A suite' } });
reporter.suiteDone({
id: 123,
description: "A suite",
description: 'A suite',
status: 'passed'
});
expect(suites).toEqual({123: {id: 123, description: "A suite", status: 'passed'}});
expect(suites).toEqual({
123: { id: 123, description: 'A suite', status: 'passed' }
});
});
describe("#specResults", function() {
describe('#specResults', function() {
var reporter, specResult1, specResult2;
beforeEach(function() {
reporter = new jasmineUnderTest.JsApiReporter({});
specResult1 = {
id: 1,
description: "A spec"
description: 'A spec'
};
specResult2 = {
id: 2,
description: "Another spec"
description: 'Another spec'
};
reporter.specDone(specResult1);
reporter.specDone(specResult2);
});
it("should return a slice of results", function() {
it('should return a slice of results', function() {
expect(reporter.specResults(0, 1)).toEqual([specResult1]);
expect(reporter.specResults(1, 1)).toEqual([specResult2]);
});
describe("when the results do not exist", function() {
it("should return a slice of shorter length", function() {
describe('when the results do not exist', function() {
it('should return a slice of shorter length', function() {
expect(reporter.specResults(0, 3)).toEqual([specResult1, specResult2]);
expect(reporter.specResults(2, 3)).toEqual([]);
});
});
});
describe("#suiteResults", function(){
describe('#suiteResults', function() {
var reporter, suiteResult1, suiteResult2;
beforeEach(function() {
reporter = new jasmineUnderTest.JsApiReporter({});
@@ -192,7 +112,7 @@ describe("JsApiReporter", function() {
};
suiteResult2 = {
id: 2,
status: 'finished'
status: 'passed'
};
reporter.suiteStarted(suiteStarted1);
@@ -200,37 +120,37 @@ describe("JsApiReporter", function() {
reporter.suiteDone(suiteResult2);
});
it('should not include suite starts', function(){
expect(reporter.suiteResults(0,3).length).toEqual(2);
it('should not include suite starts', function() {
expect(reporter.suiteResults(0, 3).length).toEqual(2);
});
it("should return a slice of results", function() {
it('should return a slice of results', function() {
expect(reporter.suiteResults(0, 1)).toEqual([suiteResult1]);
expect(reporter.suiteResults(1, 1)).toEqual([suiteResult2]);
});
it("returns nothing for out of bounds indicies", function() {
it('returns nothing for out of bounds indices', function() {
expect(reporter.suiteResults(0, 3)).toEqual([suiteResult1, suiteResult2]);
expect(reporter.suiteResults(2, 3)).toEqual([]);
});
});
describe("#executionTime", function() {
it("should start the timer when jasmine starts", function() {
describe('#executionTime', function() {
it('should start the timer when jasmine starts', function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
reporter.jasmineStarted();
expect(timerSpy.start).toHaveBeenCalled();
});
it("should return the time it took the specs to run, in ms", function() {
it('should return the time it took the specs to run, in ms', function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
timerSpy.elapsed.and.returnValue(1000);
reporter.jasmineDone();
@@ -238,11 +158,11 @@ describe("JsApiReporter", function() {
});
describe("when the specs haven't finished being run", function() {
it("should return undefined", function() {
it('should return undefined', function() {
var timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
reporter = new jasmineUnderTest.JsApiReporter({
timer: timerSpy
});
expect(reporter.executionTime()).toBeUndefined();
});
@@ -252,8 +172,8 @@ describe("JsApiReporter", function() {
describe('#runDetails', function() {
it('should have details about the run', function() {
var reporter = new jasmineUnderTest.JsApiReporter({});
reporter.jasmineDone({some: {run: 'details'}});
expect(reporter.runDetails).toEqual({some: {run: 'details'}});
reporter.jasmineDone({ some: { run: 'details' } });
expect(reporter.runDetails).toEqual({ some: { run: 'details' } });
});
});
});

View File

@@ -1,5 +1,5 @@
describe("FakeDate", function() {
it("does not fail if no global date is found", function() {
describe('FakeDate', function() {
it('does not fail if no global date is found', function() {
var fakeGlobal = {},
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
@@ -10,11 +10,11 @@ describe("FakeDate", function() {
}).not.toThrow();
});
it("replaces the global Date when it is installed", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('replaces the global Date when it is installed', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {}
}
};
}),
fakeGlobal = { Date: globalDate },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
@@ -25,11 +25,11 @@ describe("FakeDate", function() {
expect(fakeGlobal.Date).not.toEqual(globalDate);
});
it("replaces the global Date on uninstall", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('replaces the global Date on uninstall', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {}
}
};
}),
fakeGlobal = { Date: globalDate },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
@@ -40,13 +40,13 @@ describe("FakeDate", function() {
expect(fakeGlobal.Date).toEqual(globalDate);
});
it("takes the current time as the base when installing without parameters", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('takes the current time as the base when installing without parameters', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {
return 1000;
}
}
};
}),
fakeGlobal = { Date: globalDate },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
@@ -58,7 +58,7 @@ describe("FakeDate", function() {
expect(globalDate).toHaveBeenCalledWith(1000);
});
it("can accept a date as time base when installing", function() {
it('can accept a date as time base when installing', function() {
var fakeGlobal = { Date: Date },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal),
baseDate = new Date();
@@ -69,7 +69,7 @@ describe("FakeDate", function() {
expect(new fakeGlobal.Date().getTime()).toEqual(123);
});
it("makes real dates", function() {
it('makes real dates', function() {
var fakeGlobal = { Date: Date },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
@@ -78,13 +78,13 @@ describe("FakeDate", function() {
expect(new fakeGlobal.Date() instanceof fakeGlobal.Date).toBe(true);
});
it("fakes current time when using Date.now()", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('fakes current time when using Date.now()', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {
return 1000;
}
}
};
}),
fakeGlobal = { Date: globalDate };
@@ -97,28 +97,30 @@ describe("FakeDate", function() {
});
it("does not stub Date.now() if it doesn't already exist", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {
return 1000;
}
}
};
}),
fakeGlobal = { Date: globalDate },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
mockDate.install();
expect(fakeGlobal.Date.now).toThrowError("Browser does not support Date.now()");
expect(fakeGlobal.Date.now).toThrowError(
'Browser does not support Date.now()'
);
});
it("makes time passes using tick", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('makes time passes using tick', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {
return 1000;
}
}
};
}),
fakeGlobal = { Date: globalDate };
@@ -136,13 +138,13 @@ describe("FakeDate", function() {
expect(fakeGlobal.Date.now()).toEqual(2100);
});
it("allows to increase 0 milliseconds using tick", function() {
var globalDate = jasmine.createSpy("global Date").and.callFake(function() {
it('allows to increase 0 milliseconds using tick', function() {
var globalDate = jasmine.createSpy('global Date').and.callFake(function() {
return {
getTime: function() {
return 1000;
}
}
};
}),
fakeGlobal = { Date: globalDate };
@@ -158,14 +160,16 @@ describe("FakeDate", function() {
expect(fakeGlobal.Date.now()).toEqual(1000);
});
it("allows creation of a Date in a different time than the mocked time", function() {
it('allows creation of a Date in a different time than the mocked time', function() {
var fakeGlobal = { Date: Date },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
mockDate.install();
var otherDate = new fakeGlobal.Date(2013, 9, 23, 0, 0, 1, 0);
expect(otherDate.getTime()).toEqual(new Date(2013, 9, 23, 0, 0, 1, 0).getTime());
expect(otherDate.getTime()).toEqual(
new Date(2013, 9, 23, 0, 0, 1, 0).getTime()
);
});
it("allows creation of a Date that isn't fully specified", function() {
@@ -189,7 +193,7 @@ describe("FakeDate", function() {
expect(otherDate.getTime()).toEqual(now);
});
it("copies all Date properties to the mocked date", function() {
it('copies all Date properties to the mocked date', function() {
var fakeGlobal = { Date: Date },
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);

View File

@@ -1,144 +1,177 @@
describe("jasmineUnderTest.pp", function () {
it("should wrap strings in single quotes", function() {
expect(jasmineUnderTest.pp("some string")).toEqual("'some string'");
expect(jasmineUnderTest.pp("som' string")).toEqual("'som' string'");
describe('PrettyPrinter', function() {
it('should wrap strings in single quotes', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp('some string')).toEqual("'some string'");
expect(pp("som' string")).toEqual("'som' string'");
});
it("should stringify primitives properly", function() {
expect(jasmineUnderTest.pp(true)).toEqual("true");
expect(jasmineUnderTest.pp(false)).toEqual("false");
expect(jasmineUnderTest.pp(null)).toEqual("null");
expect(jasmineUnderTest.pp(jasmine.undefined)).toEqual("undefined");
expect(jasmineUnderTest.pp(3)).toEqual("3");
expect(jasmineUnderTest.pp(-3.14)).toEqual("-3.14");
expect(jasmineUnderTest.pp(-0)).toEqual("-0");
it('should stringify primitives properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(true)).toEqual('true');
expect(pp(false)).toEqual('false');
expect(pp(null)).toEqual('null');
expect(pp(jasmine.undefined)).toEqual('undefined');
expect(pp(3)).toEqual('3');
expect(pp(-3.14)).toEqual('-3.14');
expect(pp(-0)).toEqual('-0');
});
describe('stringify sets', function() {
it("should stringify sets properly", function() {
it('should stringify sets properly', function() {
jasmine.getEnv().requireFunctioningSets();
var set = new Set();
var set = new Set(); // eslint-disable-line compat/compat
set.add(1);
set.add(2);
expect(jasmineUnderTest.pp(set)).toEqual("Set( 1, 2 )");
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(set)).toEqual('Set( 1, 2 )');
});
it("should truncate sets with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it('should truncate sets with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH', function() {
jasmine.getEnv().requireFunctioningSets();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
try {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
var set = new Set();
var set = new Set(); // eslint-disable-line compat/compat
set.add('a');
set.add('b');
set.add('c');
expect(jasmineUnderTest.pp(set)).toEqual("Set( 'a', 'b', ... )");
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(set)).toEqual("Set( 'a', 'b', ... )");
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
}
})
});
});
describe('stringify maps', function() {
it("should stringify maps properly", function() {
it('should stringify maps properly', function() {
jasmine.getEnv().requireFunctioningMaps();
var map = new Map();
map.set(1,2);
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 1, 2 ] )");
var map = new Map(); // eslint-disable-line compat/compat
map.set(1, 2);
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(map)).toEqual('Map( [ 1, 2 ] )');
});
it("should truncate maps with more elments than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it('should truncate maps with more elements than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH', function() {
jasmine.getEnv().requireFunctioningMaps();
var originalMaxSize = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
try {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
var map = new Map();
map.set("a",1);
map.set("b",2);
map.set("c",3);
expect(jasmineUnderTest.pp(map)).toEqual("Map( [ 'a', 1 ], [ 'b', 2 ], ... )");
var map = new Map(); // eslint-disable-line compat/compat
map.set('a', 1);
map.set('b', 2);
map.set('c', 3);
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(map)).toEqual("Map( [ 'a', 1 ], [ 'b', 2 ], ... )");
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
}
})
});
});
describe('stringify arrays', function() {
it("should stringify arrays properly", function() {
expect(jasmineUnderTest.pp([1, 2])).toEqual("[ 1, 2 ]");
expect(jasmineUnderTest.pp([1, 'foo', {}, jasmine.undefined, null])).toEqual("[ 1, 'foo', Object({ }), undefined, null ]");
it('should stringify arrays properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp([1, 2])).toEqual('[ 1, 2 ]');
expect(pp([1, 'foo', {}, jasmine.undefined, null])).toEqual(
"[ 1, 'foo', Object({ }), undefined, null ]"
);
});
it("should truncate arrays that are longer than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH", function() {
it('should truncate arrays that are longer than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH', function() {
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var array = [1, 2, 3];
var pp = jasmineUnderTest.makePrettyPrinter();
try {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(jasmineUnderTest.pp(array)).toEqual("[ 1, 2, ... ]");
expect(pp(array)).toEqual('[ 1, 2, ... ]');
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
});
it("should stringify arrays with properties properly", function() {
it('should stringify arrays with properties properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var arr = [1, 2];
arr.foo = 'bar';
arr.baz = {};
expect(jasmineUnderTest.pp(arr)).toEqual("[ 1, 2, foo: 'bar', baz: Object({ }) ]");
expect(pp(arr)).toEqual("[ 1, 2, foo: 'bar', baz: Object({ }) ]");
});
it("should stringify empty arrays with properties properly", function() {
it('should stringify empty arrays with properties properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var empty = [];
empty.foo = 'bar';
empty.baz = {};
expect(jasmineUnderTest.pp(empty)).toEqual("[ foo: 'bar', baz: Object({ }) ]");
expect(pp(empty)).toEqual("[ foo: 'bar', baz: Object({ }) ]");
});
it("should stringify long arrays with properties properly", function() {
it('should stringify long arrays with properties properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var long = [1,2,3];
var long = [1, 2, 3];
long.foo = 'bar';
long.baz = {};
try {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(jasmineUnderTest.pp(long)).toEqual("[ 1, 2, ..., foo: 'bar', baz: Object({ }) ]");
expect(pp(long)).toEqual(
"[ 1, 2, ..., foo: 'bar', baz: Object({ }) ]"
);
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
});
it("should indicate circular array references", function() {
it('should indicate circular array references', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var array1 = [1, 2];
var array2 = [array1];
array1.push(array2);
expect(jasmineUnderTest.pp(array1)).toEqual("[ 1, 2, [ <circular reference: Array> ] ]");
expect(pp(array1)).toEqual('[ 1, 2, [ <circular reference: Array> ] ]');
});
it("should not indicate circular references incorrectly", function() {
var array = [ [1] ];
expect(jasmineUnderTest.pp(array)).toEqual("[ [ 1 ] ]");
it('should not indicate circular references incorrectly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var array = [[1]];
expect(pp(array)).toEqual('[ [ 1 ] ]');
});
});
it("should stringify objects properly", function() {
expect(jasmineUnderTest.pp({foo: 'bar'})).toEqual("Object({ foo: 'bar' })");
expect(jasmineUnderTest.pp({foo:'bar', baz:3, nullValue: null, undefinedValue: jasmine.undefined})).toEqual("Object({ foo: 'bar', baz: 3, nullValue: null, undefinedValue: undefined })");
expect(jasmineUnderTest.pp({foo: function () {
}, bar: [1, 2, 3]})).toEqual("Object({ foo: Function, bar: [ 1, 2, 3 ] })");
it('should stringify objects properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp({ foo: 'bar' })).toEqual("Object({ foo: 'bar' })");
expect(
pp({
foo: 'bar',
baz: 3,
nullValue: null,
undefinedValue: jasmine.undefined
})
).toEqual(
"Object({ foo: 'bar', baz: 3, nullValue: null, undefinedValue: undefined })"
);
expect(pp({ foo: function() {}, bar: [1, 2, 3] })).toEqual(
'Object({ foo: Function, bar: [ 1, 2, 3 ] })'
);
});
it("should truncate objects with too many keys", function () {
it('should stringify objects that almost look like DOM nodes', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp({ nodeType: 1 })).toEqual('Object({ nodeType: 1 })');
});
it('should truncate objects with too many keys', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
var long = {a: 1, b: 2, c: 3};
var long = { a: 1, b: 2, c: 3 };
try {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
expect(jasmineUnderTest.pp(long)).toEqual("Object({ a: 1, b: 2, ... })");
expect(pp(long)).toEqual('Object({ a: 1, b: 2, ... })');
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxLength;
}
@@ -155,86 +188,118 @@ describe("jasmineUnderTest.pp", function () {
}
}
it("should truncate outputs that are too long", function() {
var big = [
{ a: 1, b: "a long string" },
{}
];
it('should truncate outputs that are too long', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var big = [{ a: 1, b: 'a long string' }, {}];
withMaxChars(34, function() {
expect(jasmineUnderTest.pp(big)).toEqual("[ Object({ a: 1, b: 'a long st ...");
expect(pp(big)).toEqual("[ Object({ a: 1, b: 'a long st ...");
});
});
it("should not serialize more objects after hitting MAX_PRETTY_PRINT_CHARS", function() {
var a = { jasmineToString: function() { return 'object a'; } },
b = { jasmineToString: function() { return 'object b'; } },
c = { jasmineToString: jasmine.createSpy('c jasmineToString').and.returnValue('') },
d = { jasmineToString: jasmine.createSpy('d jasmineToString').and.returnValue('') };
it('should not serialize more objects after hitting MAX_PRETTY_PRINT_CHARS', function() {
var a = {
jasmineToString: function() {
return 'object a';
}
},
b = {
jasmineToString: function() {
return 'object b';
}
},
c = {
jasmineToString: jasmine
.createSpy('c jasmineToString')
.and.returnValue('')
},
d = {
jasmineToString: jasmine
.createSpy('d jasmineToString')
.and.returnValue('')
},
pp = jasmineUnderTest.makePrettyPrinter();
withMaxChars(30, function() {
jasmineUnderTest.pp([{a: a, b: b, c: c}, d]);
pp([{ a: a, b: b, c: c }, d]);
expect(c.jasmineToString).not.toHaveBeenCalled();
expect(d.jasmineToString).not.toHaveBeenCalled();
});
});
it("should print 'null' as the constructor of an object with its own constructor property", function() {
expect(jasmineUnderTest.pp({constructor: function() {}})).toContain("null({");
expect(jasmineUnderTest.pp({constructor: 'foo'})).toContain("null({");
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp({ constructor: function() {} })).toContain('null({');
expect(pp({ constructor: 'foo' })).toContain('null({');
});
it("should not include inherited properties when stringifying an object", function() {
it('should not include inherited properties when stringifying an object', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var SomeClass = function SomeClass() {};
SomeClass.prototype.foo = "inherited foo";
SomeClass.prototype.foo = 'inherited foo';
var instance = new SomeClass();
instance.bar = "my own bar";
expect(jasmineUnderTest.pp(instance)).toEqual("SomeClass({ bar: 'my own bar' })");
instance.bar = 'my own bar';
expect(pp(instance)).toEqual("SomeClass({ bar: 'my own bar' })");
});
it("should not recurse objects and arrays more deeply than jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH", function() {
it('should not recurse objects and arrays more deeply than jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var originalMaxDepth = jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH;
var nestedObject = { level1: { level2: { level3: { level4: "leaf" } } } };
var nestedArray = [1, [2, [3, [4, "leaf"]]]];
var nestedObject = { level1: { level2: { level3: { level4: 'leaf' } } } };
var nestedArray = [1, [2, [3, [4, 'leaf']]]];
try {
jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH = 2;
expect(jasmineUnderTest.pp(nestedObject)).toEqual("Object({ level1: Object({ level2: Object }) })");
expect(jasmineUnderTest.pp(nestedArray)).toEqual("[ 1, [ 2, Array ] ]");
expect(pp(nestedObject)).toEqual(
'Object({ level1: Object({ level2: Object }) })'
);
expect(pp(nestedArray)).toEqual('[ 1, [ 2, Array ] ]');
jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH = 3;
expect(jasmineUnderTest.pp(nestedObject)).toEqual("Object({ level1: Object({ level2: Object({ level3: Object }) }) })");
expect(jasmineUnderTest.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, Array ] ] ]");
expect(pp(nestedObject)).toEqual(
'Object({ level1: Object({ level2: Object({ level3: Object }) }) })'
);
expect(pp(nestedArray)).toEqual('[ 1, [ 2, [ 3, Array ] ] ]');
jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH = 4;
expect(jasmineUnderTest.pp(nestedObject)).toEqual("Object({ level1: Object({ level2: Object({ level3: Object({ level4: 'leaf' }) }) }) })");
expect(jasmineUnderTest.pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
expect(pp(nestedObject)).toEqual(
"Object({ level1: Object({ level2: Object({ level3: Object({ level4: 'leaf' }) }) }) })"
);
expect(pp(nestedArray)).toEqual("[ 1, [ 2, [ 3, [ 4, 'leaf' ] ] ] ]");
} finally {
jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH = originalMaxDepth;
}
});
it("should stringify immutable circular objects", function(){
if(Object.freeze){
var frozenObject = {foo: {bar: 'baz'}};
it('should stringify immutable circular objects', function() {
if (Object.freeze) {
var pp = jasmineUnderTest.makePrettyPrinter();
var frozenObject = { foo: { bar: 'baz' } };
frozenObject.circular = frozenObject;
frozenObject = Object.freeze(frozenObject);
expect(jasmineUnderTest.pp(frozenObject)).toEqual("Object({ foo: Object({ bar: 'baz' }), circular: <circular reference: Object> })");
expect(pp(frozenObject)).toEqual(
"Object({ foo: Object({ bar: 'baz' }), circular: <circular reference: Object> })"
);
}
});
it("should stringify RegExp objects properly", function() {
expect(jasmineUnderTest.pp(/x|y|z/)).toEqual("/x|y|z/");
it('should stringify RegExp objects properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(/x|y|z/)).toEqual('/x|y|z/');
});
it("should indicate circular object references", function() {
var sampleValue = {foo: 'hello'};
it('should indicate circular object references', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var sampleValue = { foo: 'hello' };
sampleValue.nested = sampleValue;
expect(jasmineUnderTest.pp(sampleValue)).toEqual("Object({ foo: 'hello', nested: <circular reference: Object> })");
expect(pp(sampleValue)).toEqual(
"Object({ foo: 'hello', nested: <circular reference: Object> })"
);
});
it("should indicate getters on objects as such", function() {
var sampleValue = {id: 1};
it('should indicate getters on objects as such', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var sampleValue = { id: 1 };
if (sampleValue.__defineGetter__) {
//not supported in IE!
sampleValue.__defineGetter__('calculatedValue', function() {
@@ -242,96 +307,260 @@ describe("jasmineUnderTest.pp", function () {
});
}
if (sampleValue.__defineGetter__) {
expect(jasmineUnderTest.pp(sampleValue)).toEqual("Object({ id: 1, calculatedValue: <getter> })");
}
else {
expect(jasmineUnderTest.pp(sampleValue)).toEqual("Object({ id: 1 })");
expect(pp(sampleValue)).toEqual(
'Object({ id: 1, calculatedValue: <getter> })'
);
} else {
expect(pp(sampleValue)).toEqual('Object({ id: 1 })');
}
});
it('should not do HTML escaping of strings', function() {
expect(jasmineUnderTest.pp('some <b>html string</b> &', false)).toEqual('\'some <b>html string</b> &\'');
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp('some <b>html string</b> &', false)).toEqual(
"'some <b>html string</b> &'"
);
});
it("should abbreviate the global (usually window) object", function() {
expect(jasmineUnderTest.pp(jasmine.getGlobal())).toEqual("<global>");
it('should abbreviate the global (usually window) object', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
expect(pp(jasmine.getGlobal())).toEqual('<global>');
});
it("should stringify Date objects properly", function() {
it('should stringify Date objects properly', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var now = new Date();
expect(jasmineUnderTest.pp(now)).toEqual("Date(" + now.toString() + ")");
expect(pp(now)).toEqual('Date(' + now.toString() + ')');
});
it("should stringify spy objects properly", function() {
var TestObject = {
someFunction: function() {}
},
env = new jasmineUnderTest.Env();
describe('with a spy object', function() {
var env, pp;
var spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() {return [];}});
beforeEach(function() {
env = new jasmineUnderTest.Env();
pp = jasmineUnderTest.makePrettyPrinter();
});
spyRegistry.spyOn(TestObject, 'someFunction');
expect(jasmineUnderTest.pp(TestObject.someFunction)).toEqual("spy on someFunction");
afterEach(function() {
env.cleanup_();
});
expect(jasmineUnderTest.pp(jasmineUnderTest.createSpy("something"))).toEqual("spy on something");
it('should stringify spy objects properly', function() {
var TestObject = {
someFunction: function() {}
};
var spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return [];
},
createSpy: function(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
});
spyRegistry.spyOn(TestObject, 'someFunction');
expect(pp(TestObject.someFunction)).toEqual('spy on someFunction');
expect(pp(env.createSpy('something'))).toEqual('spy on something');
});
it('should stringify spyOn toString properly', function() {
var TestObject = {
someFunction: function() {}
},
env = new jasmineUnderTest.Env(),
pp = jasmineUnderTest.makePrettyPrinter();
var spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return [];
},
createSpy: function(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
});
spyRegistry.spyOn(TestObject, 'toString');
var testSpyObj = env.createSpyObj('TheClassName', ['toString']);
expect(pp(testSpyObj)).toEqual('spy on TheClassName.toString');
});
});
it("should stringify objects that implement jasmineToString", function () {
it('should stringify objects that implement jasmineToString', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var obj = {
jasmineToString: function () { return "strung"; }
jasmineToString: function() {
return 'strung';
}
};
expect(jasmineUnderTest.pp(obj)).toEqual("strung");
expect(pp(obj)).toEqual('strung');
});
it("should stringify objects that implement custom toString", function () {
it('should pass itself to jasmineToString', function() {
var pp = jasmineUnderTest.makePrettyPrinter([]);
var obj = {
toString: function () { return "my toString"; }
jasmineToString: jasmine.createSpy('jasmineToString').and.returnValue('')
};
expect(jasmineUnderTest.pp(obj)).toEqual("my toString");
pp(obj);
expect(obj.jasmineToString).toHaveBeenCalledWith(pp);
});
it('should stringify objects that implement custom toString', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var obj = {
toString: function() {
return 'my toString';
}
};
expect(pp(obj)).toEqual('my toString');
// Simulate object from another global context (e.g. an iframe or Web Worker) that does not actually have a custom
// toString despite obj.toString !== Object.prototype.toString
var objFromOtherContext = {
foo: 'bar',
toString: function () { return Object.prototype.toString.call(this); }
toString: function() {
return Object.prototype.toString.call(this);
}
};
if (jasmine.getEnv().ieVersion < 9) {
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar' })");
} else {
expect(jasmineUnderTest.pp(objFromOtherContext)).toEqual("Object({ foo: 'bar', toString: Function })");
}
expect(pp(objFromOtherContext)).toEqual(
"Object({ foo: 'bar', toString: Function })"
);
});
it("should stringify objects have have a toString that isn't a function", function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var obj = {
toString: "foo"
toString: 'foo'
};
if (jasmine.getEnv().ieVersion < 9) {
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ })");
} else {
expect(jasmineUnderTest.pp(obj)).toEqual("Object({ toString: 'foo' })");
}
expect(pp(obj)).toEqual("Object({ toString: 'foo' })");
});
it("should stringify objects from anonymous constructors with custom toString", function () {
var MyAnonymousConstructor = (function() { return function () {}; })();
MyAnonymousConstructor.toString = function () { return ''; };
it('should stringify objects from anonymous constructors with custom toString', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var MyAnonymousConstructor = (function() {
return function() {};
})();
MyAnonymousConstructor.toString = function() {
return '';
};
var a = new MyAnonymousConstructor();
expect(jasmineUnderTest.pp(a)).toEqual("<anonymous>({ })");
expect(pp(a)).toEqual('<anonymous>({ })');
});
it("should handle objects with null prototype", function() {
if (jasmine.getEnv().ieVersion < 9) { return; }
it('should handle objects with null prototype', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var obj = Object.create(null);
obj.foo = 'bar';
expect(jasmineUnderTest.pp(obj)).toEqual("null({ foo: 'bar' })");
expect(pp(obj)).toEqual("null({ foo: 'bar' })");
});
it('should gracefully handle objects with invalid toString implementations', function() {
var pp = jasmineUnderTest.makePrettyPrinter();
var obj = {
foo: {
toString: function() {
// Invalid: toString returning a number
return 3;
}
},
bar: {
toString: function() {
// Really invalid: a nested bad toString().
return {
toString: function() {
return new Date();
}
};
}
},
// Valid: an actual number
baz: 3,
// Valid: an actual Error object
qux: new Error('bar'),
//
baddy: {
toString: function() {
throw new Error('I am a bad toString');
}
}
};
expect(pp(obj)).toEqual(
'Object({ foo: [object Number], bar: [object Object], baz: 3, qux: Error: bar, baddy: has-invalid-toString-method })'
);
});
describe('Custom object formatters', function() {
it('should use the first custom object formatter that does not return undefined', function() {
var customObjectFormatters = [
function(obj) {
return undefined;
},
function(obj) {
return '2nd: ' + obj.foo;
},
function(obj) {
return '3rd: ' + obj.foo;
}
],
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
obj = { foo: 'bar' };
expect(pp(obj)).toEqual('2nd: bar');
});
it('should fall back to built in logic if all custom object formatters return undefined', function() {
var customObjectFormatters = [
function(obj) {
return undefined;
}
],
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
obj = { foo: 'bar' };
expect(pp(obj)).toEqual("Object({ foo: 'bar' })");
});
});
describe('#customFormat_', function() {
it('should use the first custom object formatter that does not return undefined', function() {
var customObjectFormatters = [
function(obj) {
return undefined;
},
function(obj) {
return '2nd: ' + obj.foo;
},
function(obj) {
return '3rd: ' + obj.foo;
}
],
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
obj = { foo: 'bar' };
expect(pp.customFormat_(obj)).toEqual('2nd: bar');
});
it('should return undefined if all custom object formatters return undefined', function() {
var customObjectFormatters = [
function(obj) {
return undefined;
}
],
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
obj = { foo: 'bar' };
expect(pp.customFormat_(obj)).toBeUndefined();
});
});
});

View File

@@ -1,5 +1,4 @@
describe("QueueRunner", function() {
describe('QueueRunner', function() {
it("runs all the functions it's passed", function() {
var calls = [],
queueableFn1 = { fn: jasmine.createSpy('fn1') },
@@ -19,7 +18,7 @@ describe("QueueRunner", function() {
expect(calls).toEqual(['fn1', 'fn2']);
});
it("runs cleanup functions after the others", function() {
it('runs cleanup functions after the others', function() {
var calls = [],
queueableFn1 = { fn: jasmine.createSpy('fn1') },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
@@ -41,12 +40,17 @@ describe("QueueRunner", function() {
it("calls each function with a consistent 'this'-- an empty object", function() {
var queueableFn1 = { fn: jasmine.createSpy('fn1') },
queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueableFn3 = { fn: function(done) { asyncContext = this; done(); } },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2, queueableFn3]
}),
asyncContext;
queueableFn2 = { fn: jasmine.createSpy('fn2') },
queueableFn3 = {
fn: function(done) {
asyncContext = this;
done();
}
},
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2, queueableFn3]
}),
asyncContext;
queueRunner.execute();
@@ -56,7 +60,7 @@ describe("QueueRunner", function() {
expect(asyncContext).toBe(context);
});
describe("with an asynchronous function", function() {
describe('with an asynchronous function', function() {
beforeEach(function() {
jasmine.clock().install();
});
@@ -65,7 +69,7 @@ describe("QueueRunner", function() {
jasmine.clock().uninstall();
});
it("supports asynchronous functions, only advancing to next function after a done() callback", function() {
it('supports asynchronous functions, only advancing to next function after a done() callback', function() {
//TODO: it would be nice if spy arity could match the fake, so we could do something like:
//createSpy('asyncfn').and.callFake(function(done) {});
@@ -73,18 +77,24 @@ describe("QueueRunner", function() {
beforeCallback = jasmine.createSpy('beforeCallback'),
fnCallback = jasmine.createSpy('fnCallback'),
afterCallback = jasmine.createSpy('afterCallback'),
queueableFn1 = { fn: function(done) {
beforeCallback();
setTimeout(done, 100);
} },
queueableFn2 = { fn: function(done) {
fnCallback();
setTimeout(done, 100);
} },
queueableFn3 = { fn: function(done) {
afterCallback();
setTimeout(done, 100);
} },
queueableFn1 = {
fn: function(done) {
beforeCallback();
setTimeout(done, 100);
}
},
queueableFn2 = {
fn: function(done) {
fnCallback();
setTimeout(done, 100);
}
},
queueableFn3 = {
fn: function(done) {
afterCallback();
setTimeout(done, 100);
}
},
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2, queueableFn3],
onComplete: onComplete
@@ -113,10 +123,14 @@ describe("QueueRunner", function() {
expect(onComplete).toHaveBeenCalled();
});
it("explicitly fails an async function with a provided fail function and moves to the next function", function() {
var queueableFn1 = { fn: function(done) {
setTimeout(function() { done.fail('foo'); }, 100);
} },
it('explicitly fails an async function with a provided fail function and moves to the next function', function() {
var queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done.fail('foo');
}, 100);
}
},
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
@@ -135,9 +149,63 @@ describe("QueueRunner", function() {
expect(queueableFn2.fn).toHaveBeenCalled();
});
it('explicitly fails an async function when next is called with an Error and moves to the next function', function() {
var err = new Error('foo'),
queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done(err);
}, 100);
}
},
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
fail: failFn
});
queueRunner.execute();
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100);
expect(failFn).toHaveBeenCalledWith(err);
expect(queueableFn2.fn).toHaveBeenCalled();
});
it('does not cause an explicit fail if execution is being stopped', function() {
var err = new jasmineUnderTest.StopExecutionError('foo'),
queueableFn1 = {
fn: function(done) {
setTimeout(function() {
done(err);
}, 100);
}
},
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
fail: failFn
});
queueRunner.execute();
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).not.toHaveBeenCalled();
jasmine.clock().tick(100);
expect(failFn).not.toHaveBeenCalled();
expect(queueableFn2.fn).toHaveBeenCalled();
});
it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() {
var timeout = 3,
beforeFn = { fn: function(done) { }, type: 'before', timeout: function() { return timeout; } },
beforeFn = { fn: function(done) {}, type: 'before', timeout: timeout },
queueableFn = { fn: jasmine.createSpy('fn'), type: 'queueable' },
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
@@ -157,15 +225,15 @@ describe("QueueRunner", function() {
expect(onComplete).toHaveBeenCalled();
});
it("by default does not set a timeout for asynchronous functions", function() {
var beforeFn = { fn: function(done) { } },
it('by default does not set a timeout for asynchronous functions', function() {
var beforeFn = { fn: function(done) {} },
queueableFn = { fn: jasmine.createSpy('fn') },
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [beforeFn, queueableFn],
onComplete: onComplete,
onException: onException,
onException: onException
});
queueRunner.execute();
@@ -178,8 +246,12 @@ describe("QueueRunner", function() {
expect(onComplete).not.toHaveBeenCalled();
});
it("clears the timeout when an async function throws an exception, to prevent additional exception reporting", function() {
var queueableFn = { fn: function(done) { throw new Error("error!"); } },
it('clears the timeout when an async function throws an exception, to prevent additional exception reporting', function() {
var queueableFn = {
fn: function(done) {
throw new Error('error!');
}
},
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({
@@ -197,8 +269,12 @@ describe("QueueRunner", function() {
expect(onException.calls.count()).toEqual(1);
});
it("clears the timeout when the done callback is called", function() {
var queueableFn = { fn: function(done) { done(); } },
it('clears the timeout when the done callback is called', function() {
var queueableFn = {
fn: function(done) {
done();
}
},
onComplete = jasmine.createSpy('onComplete'),
onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({
@@ -216,8 +292,13 @@ describe("QueueRunner", function() {
expect(onException).not.toHaveBeenCalled();
});
it("only moves to the next spec the first time you call done", function() {
var queueableFn = { fn: function(done) {done(); done();} },
it('only moves to the next spec the first time you call done', function() {
var queueableFn = {
fn: function(done) {
done();
done();
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn]
@@ -228,27 +309,31 @@ describe("QueueRunner", function() {
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
});
it("does not move to the next spec if done is called after an exception has ended the spec", function() {
var queueableFn = { fn: function(done) {
setTimeout(done, 1);
throw new Error('error!');
} },
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn]
});
it('does not move to the next spec if done is called after an exception has ended the spec', function() {
var queueableFn = {
fn: function(done) {
setTimeout(done, 1);
throw new Error('error!');
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn]
});
queueRunner.execute();
jasmine.clock().tick(1);
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
});
it("should return a null when you call done", function () {
it('should return a null when you call done', function() {
// Some promises want handlers to return anything but undefined to help catch "forgotten returns".
var doneReturn,
queueableFn = { fn: function(done) {
doneReturn = done();
} },
queueableFn = {
fn: function(done) {
doneReturn = done();
}
},
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn]
});
@@ -257,24 +342,36 @@ describe("QueueRunner", function() {
expect(doneReturn).toBe(null);
});
it("continues running functions when an exception is thrown in async code without timing out", function() {
var queueableFn = { fn: function(done) { throwAsync(); }, timeout: function() { return 1; } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
it('continues running functions when an exception is thrown in async code without timing out', function() {
var queueableFn = {
fn: function(done) {
throwAsync();
},
timeout: 1
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
onException = jasmine.createSpy('onException'),
globalErrors = { pushListener: jasmine.createSpy('pushListener'), popListener: jasmine.createSpy('popListener') },
globalErrors = {
pushListener: jasmine.createSpy('pushListener'),
popListener: jasmine.createSpy('popListener')
},
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
onException: onException,
globalErrors: globalErrors
}),
throwAsync = function() {
globalErrors.pushListener.calls.mostRecent().args[0](new Error('foo'));
globalErrors.pushListener.calls
.mostRecent()
.args[0](new Error('foo'));
jasmine.clock().tick(2);
};
nextQueueableFn.fn.and.callFake(function() {
// should remove the same function that was added
expect(globalErrors.popListener).toHaveBeenCalledWith(globalErrors.pushListener.calls.argsFor(1)[0]);
expect(globalErrors.popListener).toHaveBeenCalledWith(
globalErrors.pushListener.calls.argsFor(1)[0]
);
});
queueRunner.execute();
@@ -289,28 +386,37 @@ describe("QueueRunner", function() {
}
};
}
expect(onException).not.toHaveBeenCalledWith(errorWithMessage(/DEFAULT_TIMEOUT_INTERVAL/));
expect(onException).not.toHaveBeenCalledWith(
errorWithMessage(/DEFAULT_TIMEOUT_INTERVAL/)
);
expect(onException).toHaveBeenCalledWith(errorWithMessage(/^foo$/));
expect(nextQueueableFn.fn).toHaveBeenCalled();
});
it("handles exceptions thrown while waiting for the stack to clear", function() {
var queueableFn = { fn: function(done) { done() } },
global = {},
errorListeners = [],
globalErrors = {
pushListener: function(f) { errorListeners.push(f); },
popListener: function() { errorListeners.pop(); }
},
clearStack = jasmine.createSpy('clearStack'),
onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
globalErrors: globalErrors,
clearStack: clearStack,
onException: onException
}),
error = new Error('nope');
it('handles exceptions thrown while waiting for the stack to clear', function() {
var queueableFn = {
fn: function(done) {
done();
}
},
errorListeners = [],
globalErrors = {
pushListener: function(f) {
errorListeners.push(f);
},
popListener: function() {
errorListeners.pop();
}
},
clearStack = jasmine.createSpy('clearStack'),
onException = jasmine.createSpy('onException'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
globalErrors: globalErrors,
clearStack: clearStack,
onException: onException
}),
error = new Error('nope');
queueRunner.execute();
jasmine.clock().tick();
@@ -322,7 +428,7 @@ describe("QueueRunner", function() {
});
});
describe("with a function that returns a promise", function() {
describe('with a function that returns a promise', function() {
function StubPromise() {}
StubPromise.prototype.then = function(resolve, reject) {
@@ -338,28 +444,32 @@ describe("QueueRunner", function() {
jasmine.clock().uninstall();
});
it("runs the function asynchronously, advancing once the promise is settled", function() {
it('runs the function asynchronously, advancing once the promise is settled', function() {
var onComplete = jasmine.createSpy('onComplete'),
fnCallback = jasmine.createSpy('fnCallback'),
fnCallback = jasmine.createSpy('fnCallback'),
p1 = new StubPromise(),
p2 = new StubPromise(),
queueableFn1 = { fn: function() {
setTimeout(function() {
p1.resolveHandler();
}, 100);
return p1;
} };
queueableFn2 = { fn: function() {
queueableFn1 = {
fn: function() {
setTimeout(function() {
p1.resolveHandler();
}, 100);
return p1;
}
};
(queueableFn2 = {
fn: function() {
fnCallback();
setTimeout(function() {
p2.resolveHandler();
}, 100);
return p2;
} },
queueRunner = new jasmineUnderTest.QueueRunner({
}
}),
(queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
onComplete: onComplete
});
}));
queueRunner.execute();
expect(fnCallback).not.toHaveBeenCalled();
@@ -375,16 +485,17 @@ describe("QueueRunner", function() {
expect(onComplete).toHaveBeenCalled();
});
it("handles a rejected promise like an unhandled exception", function() {
it('handles a rejected promise like an unhandled exception', function() {
var promise = new StubPromise(),
queueableFn1 = { fn: function() {
setTimeout(function() {
promise.rejectHandler('foo')
}, 100);
return promise;
} },
queueableFn1 = {
fn: function() {
setTimeout(function() {
promise.rejectHandler('foo');
}, 100);
return promise;
}
},
queueableFn2 = { fn: jasmine.createSpy('fn2') },
failFn = jasmine.createSpy('fail'),
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn1, queueableFn2],
@@ -401,13 +512,85 @@ describe("QueueRunner", function() {
expect(onExceptionCallback).toHaveBeenCalledWith('foo');
expect(queueableFn2.fn).toHaveBeenCalled();
});
it('issues a deprecation if the function also takes a parameter', function() {
var queueableFn = {
fn: function(done) {
return new StubPromise();
}
},
deprecated = jasmine.createSpy('deprecated'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
deprecated: deprecated
}),
env = jasmineUnderTest.getEnv();
queueRunner.execute();
expect(deprecated).toHaveBeenCalledWith(
'An asynchronous ' +
'before/it/after function took a done callback but also returned a ' +
'promise. This is not supported and will stop working in the future. ' +
'Either remove the done callback (recommended) or change the function ' +
'to not return a promise.'
);
});
it('issues a more specific deprecation if the function is `async`', function() {
jasmine.getEnv().requireAsyncAwait();
eval('var fn = async function(done){};');
var deprecated = jasmine.createSpy('deprecated'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [{ fn: fn }],
deprecated: deprecated
});
queueRunner.execute();
expect(deprecated).toHaveBeenCalledWith(
'An asynchronous ' +
'before/it/after function was defined with the async keyword but ' +
'also took a done callback. This is not supported and will stop ' +
'working in the future. Either remove the done callback ' +
'(recommended) or remove the async keyword.'
);
});
});
it("calls exception handlers when an exception is thrown in a fn", function() {
var queueableFn = { type: 'queueable',
fn: function() {
throw new Error('fake error');
} },
it('passes the error instance to exception handlers in HTML browsers', function() {
var error = new Error('fake error'),
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new jasmineUnderTest.QueueRunner({
onException: onExceptionCallback
});
queueRunner.execute();
queueRunner.handleFinalError(error.message, 'fake.js', 1, 1, error);
expect(onExceptionCallback).toHaveBeenCalledWith(error);
});
it('passes the first argument to exception handlers for compatibility', function() {
var error = new Error('fake error'),
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new jasmineUnderTest.QueueRunner({
onException: onExceptionCallback
});
queueRunner.execute();
queueRunner.handleFinalError(error.message);
expect(onExceptionCallback).toHaveBeenCalledWith(error.message);
});
it('calls exception handlers when an exception is thrown in a fn', function() {
var queueableFn = {
type: 'queueable',
fn: function() {
throw new Error('fake error');
}
},
onExceptionCallback = jasmine.createSpy('on exception callback'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
@@ -419,23 +602,13 @@ describe("QueueRunner", function() {
expect(onExceptionCallback).toHaveBeenCalledWith(jasmine.any(Error));
});
it("rethrows an exception if told to", function() {
var queueableFn = { fn: function() {
throw new Error('fake error');
} },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
catchException: function(e) { return false; }
});
expect(function() {
queueRunner.execute();
}).toThrowError('fake error');
});
it("continues running the functions even after an exception is thrown in an async spec", function() {
var queueableFn = { fn: function(done) { throw new Error("error"); } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
it('continues running the functions even after an exception is thrown in an async spec', function() {
var queueableFn = {
fn: function(done) {
throw new Error('error');
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn]
});
@@ -444,26 +617,39 @@ describe("QueueRunner", function() {
expect(nextQueueableFn.fn).toHaveBeenCalled();
});
describe("When configured to complete on first error", function() {
it("skips to cleanup functions on the first exception", function() {
var queueableFn = { fn: function() { throw new Error("error"); } },
nextQueueableFn = { fn: jasmine.createSpy("nextFunction") },
cleanupFn = { fn: jasmine.createSpy("cleanup") },
describe('When configured to complete on first error', function() {
it('skips to cleanup functions on the first exception', function() {
var queueableFn = {
fn: function() {
throw new Error('error');
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
cleanupFn = { fn: jasmine.createSpy('cleanup') },
onComplete = jasmine.createSpy('onComplete'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
onComplete: onComplete,
completeOnFirstError: true
});
queueRunner.execute();
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
expect(onComplete).toHaveBeenCalledWith(
jasmine.any(jasmineUnderTest.StopExecutionError)
);
});
it("does not skip when a cleanup function throws", function() {
var queueableFn = { fn: function() { } },
cleanupFn1 = { fn: function() { throw new Error("error"); } },
cleanupFn2 = { fn: jasmine.createSpy("cleanupFn2") },
it('does not skip when a cleanup function throws', function() {
var queueableFn = { fn: function() {} },
cleanupFn1 = {
fn: function() {
throw new Error('error');
}
},
cleanupFn2 = { fn: jasmine.createSpy('cleanupFn2') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn],
cleanupFns: [cleanupFn1, cleanupFn2],
@@ -474,7 +660,7 @@ describe("QueueRunner", function() {
expect(cleanupFn2.fn).toHaveBeenCalled();
});
describe("with an asynchronous function", function() {
describe('with an asynchronous function', function() {
beforeEach(function() {
jasmine.clock().install();
});
@@ -483,39 +669,71 @@ describe("QueueRunner", function() {
jasmine.clock().uninstall();
});
it("skips to cleanup functions on the first exception", function() {
it('skips to cleanup functions once the fn completes after an unhandled exception', function() {
var errorListeners = [],
queueableFn = { fn: function(done) {} },
queueableFn = {
fn: function(done) {
queueableFnDone = done;
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
cleanupFn = { fn: jasmine.createSpy('cleanup') },
queueRunner = new jasmineUnderTest.QueueRunner({
globalErrors: {
pushListener: function(f) { errorListeners.push(f); },
popListener: function() { errorListeners.pop(); },
pushListener: function(f) {
errorListeners.push(f);
},
popListener: function() {
errorListeners.pop();
}
},
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
completeOnFirstError: true,
});
completeOnFirstError: true
}),
queueableFnDone;
queueRunner.execute();
errorListeners[errorListeners.length - 1](new Error('error'));
expect(cleanupFn.fn).not.toHaveBeenCalled();
queueableFnDone();
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
});
it("skips to cleanup functions when next.fail is called", function() {
var queueableFn = { fn: function(done) {
done.fail('nope');
} },
it('skips to cleanup functions when next.fail is called', function() {
var queueableFn = {
fn: function(done) {
done.fail('nope');
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
cleanupFn = { fn: jasmine.createSpy('cleanup') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
completeOnFirstError: true,
});
completeOnFirstError: true
});
queueRunner.execute();
jasmine.clock().tick();
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
expect(cleanupFn.fn).toHaveBeenCalled();
});
it('skips to cleanup functions when next is called with an Error', function() {
var queueableFn = {
fn: function(done) {
done(new Error('nope'));
}
},
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
cleanupFn = { fn: jasmine.createSpy('cleanup') },
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [queueableFn, nextQueueableFn],
cleanupFns: [cleanupFn],
completeOnFirstError: true
});
queueRunner.execute();
jasmine.clock().tick();
@@ -525,7 +743,7 @@ describe("QueueRunner", function() {
});
});
it("calls a provided complete callback when done", function() {
it('calls a provided complete callback when done', function() {
var queueableFn = { fn: jasmine.createSpy('fn') },
completeCallback = jasmine.createSpy('completeCallback'),
queueRunner = new jasmineUnderTest.QueueRunner({
@@ -538,7 +756,7 @@ describe("QueueRunner", function() {
expect(completeCallback).toHaveBeenCalled();
});
describe("clearing the stack", function() {
describe('clearing the stack', function() {
beforeEach(function() {
jasmine.clock().install();
});
@@ -547,18 +765,24 @@ describe("QueueRunner", function() {
jasmine.clock().uninstall();
});
it("calls a provided stack clearing function when done", function() {
var asyncFn = { fn: function(done) { done() } },
afterFn = { fn: jasmine.createSpy('afterFn') },
completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [asyncFn, afterFn],
clearStack: clearStack,
onComplete: completeCallback
});
it('calls a provided stack clearing function when done', function() {
var asyncFn = {
fn: function(done) {
done();
}
},
afterFn = { fn: jasmine.createSpy('afterFn') },
completeCallback = jasmine.createSpy('completeCallback'),
clearStack = jasmine.createSpy('clearStack'),
queueRunner = new jasmineUnderTest.QueueRunner({
queueableFns: [asyncFn, afterFn],
clearStack: clearStack,
onComplete: completeCallback
});
clearStack.and.callFake(function(fn) { fn(); });
clearStack.and.callFake(function(fn) {
fn();
});
queueRunner.execute();
jasmine.clock().tick();
@@ -580,9 +804,7 @@ describe("QueueRunner", function() {
});
it('runs the functions on the scope of a UserContext', function() {
var calls = [],
context;
var context;
this.fn.and.callFake(function() {
context = this;
});
@@ -606,8 +828,7 @@ describe("QueueRunner", function() {
});
it('runs the functions on the scope of a UserContext', function() {
var calls = [],
context;
var context;
this.fn.and.callFake(function() {
context = this;
});

View File

@@ -1,78 +1,177 @@
describe("ReportDispatcher", function() {
it("builds an interface of requested methods", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar', 'baz']);
describe('ReportDispatcher', function() {
it('builds an interface of requested methods', function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher([
'foo',
'bar',
'baz'
]);
expect(dispatcher.foo).toBeDefined();
expect(dispatcher.bar).toBeDefined();
expect(dispatcher.baz).toBeDefined();
});
it("dispatches requested methods to added reporters", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
it('dispatches requested methods to added reporters', function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(
['foo', 'bar'],
queueRunnerFactory
),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.addReporter(reporter);
dispatcher.addReporter(anotherReporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [
{ fn: jasmine.any(Function) },
{ fn: jasmine.any(Function) }
],
isReporter: true
})
);
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
expect(reporter.foo.calls.mostRecent().object).toBe(reporter);
fns[1].fn();
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
expect(anotherReporter.foo.calls.mostRecent().object).toBe(anotherReporter);
dispatcher.bar('a', 'b');
queueRunnerFactory.calls.reset();
dispatcher.bar('a', 'b', completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [
{ fn: jasmine.any(Function) },
{ fn: jasmine.any(Function) }
],
isReporter: true
})
);
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
fns[1].fn();
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
});
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo']),
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(
['foo'],
queueRunnerFactory
),
reporter = jasmine.createSpyObj('reporter', ['baz']);
dispatcher.addReporter(reporter);
expect(function() {
dispatcher.foo(123, 456);
}).not.toThrow();
dispatcher.foo(123, 456);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: []
})
);
});
it("allows providing a fallback reporter in case there's no other report", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
it("allows providing a fallback reporter in case there's no other reporter", function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(
['foo', 'bar'],
queueRunnerFactory
),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.provideFallbackReporter(reporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [{ fn: jasmine.any(Function) }],
isReporter: true
})
);
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
});
it("does not call fallback reporting methods when another report is provided", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
it('does not call fallback reporting methods when another reporter is provided', function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(
['foo', 'bar'],
queueRunnerFactory
),
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']);
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.provideFallbackReporter(fallbackReporter);
dispatcher.addReporter(reporter);
dispatcher.foo(123, 456);
dispatcher.foo(123, 456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [{ fn: jasmine.any(Function) }],
isReporter: true
})
);
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
expect(fallbackReporter.foo).not.toHaveBeenCalledWith(123, 456);
});
it("allows registered reporters to be cleared", function() {
var dispatcher = new jasmineUnderTest.ReportDispatcher(['foo', 'bar']),
reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']),
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']);
it('allows registered reporters to be cleared', function() {
var queueRunnerFactory = jasmine.createSpy('queueRunner'),
dispatcher = new jasmineUnderTest.ReportDispatcher(
['foo', 'bar'],
queueRunnerFactory
),
reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']),
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']),
completeCallback = jasmine.createSpy('complete');
dispatcher.addReporter(reporter1);
dispatcher.foo(123);
dispatcher.foo(123, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [{ fn: jasmine.any(Function) }],
isReporter: true
})
);
var fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter1.foo).toHaveBeenCalledWith(123);
dispatcher.clearReporters();
dispatcher.addReporter(reporter2);
dispatcher.bar(456);
dispatcher.bar(456, completeCallback);
expect(queueRunnerFactory).toHaveBeenCalledWith(
jasmine.objectContaining({
queueableFns: [{ fn: jasmine.any(Function) }],
isReporter: true
})
);
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
fns[0].fn();
expect(reporter1.bar).not.toHaveBeenCalled();
expect(reporter2.bar).toHaveBeenCalledWith(456);
});

View File

@@ -1,25 +1,30 @@
describe("Spec", function() {
it("#isPendingSpecException returns true for a pending spec exception", function() {
describe('Spec', function() {
it('#isPendingSpecException returns true for a pending spec exception', function() {
var e = new Error(jasmineUnderTest.Spec.pendingSpecExceptionMessage);
expect(jasmineUnderTest.Spec.isPendingSpecException(e)).toBe(true);
});
it("#isPendingSpecException returns true for a pending spec exception (even when FF bug is present)", function() {
it('#isPendingSpecException returns true for a pending spec exception (even when FF bug is present)', function() {
var fakeError = {
toString: function() { return "Error: " + jasmineUnderTest.Spec.pendingSpecExceptionMessage; }
toString: function() {
return 'Error: ' + jasmineUnderTest.Spec.pendingSpecExceptionMessage;
}
};
expect(jasmineUnderTest.Spec.isPendingSpecException(fakeError)).toBe(true);
});
it("#isPendingSpecException returns true for a pending spec exception with a custom message", function() {
expect(jasmineUnderTest.Spec.isPendingSpecException(jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'foo')).toBe(true);
it('#isPendingSpecException returns true for a pending spec exception with a custom message', function() {
expect(
jasmineUnderTest.Spec.isPendingSpecException(
jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'foo'
)
).toBe(true);
});
it("#isPendingSpecException returns false for not a pending spec exception", function() {
var e = new Error("foo");
it('#isPendingSpecException returns false for not a pending spec exception', function() {
var e = new Error('foo');
expect(jasmineUnderTest.Spec.isPendingSpecException(e)).toBe(false);
});
@@ -28,7 +33,7 @@ describe("Spec", function() {
expect(jasmineUnderTest.Spec.isPendingSpecException(void 0)).toBe(false);
});
it("delegates execution to a QueueRunner", function() {
it('delegates execution to a QueueRunner', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
spec = new jasmineUnderTest.Spec({
description: 'my test',
@@ -42,7 +47,7 @@ describe("Spec", function() {
expect(fakeQueueRunner).toHaveBeenCalled();
});
it("should call the start callback on execution", function() {
it('should call the start callback on execution', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
spec = new jasmineUnderTest.Spec({
@@ -55,6 +60,7 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
// TODO: due to some issue with the Pretty Printer, this line fails, but the other two pass.
// This means toHaveBeenCalledWith on IE8 will always be broken.
@@ -63,18 +69,22 @@ describe("Spec", function() {
expect(startCallback.calls.first().object).toEqual(spec);
});
it("should call the start callback on execution but before any befores are called", function() {
it('should call the start callback on execution but before any befores are called', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
beforesWereCalled = false,
startCallback = jasmine.createSpy('start-callback').and.callFake(function() {
expect(beforesWereCalled).toBe(false);
}),
startCallback = jasmine
.createSpy('start-callback')
.and.callFake(function() {
expect(beforesWereCalled).toBe(false);
}),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
beforeFns: function() {
return [function() {
beforesWereCalled = true
}]
return [
function() {
beforesWereCalled = true;
}
];
},
onStart: startCallback,
queueRunnerFactory: fakeQueueRunner
@@ -82,21 +92,24 @@ describe("Spec", function() {
spec.execute();
fakeQueueRunner.calls.mostRecent().args[0].queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
});
it("provides all before fns and after fns to be run", function() {
it('provides all before fns and after fns to be run', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
before = jasmine.createSpy('before'),
after = jasmine.createSpy('after'),
queueableFn = { fn: jasmine.createSpy('test body').and.callFake(function() {
expect(before).toHaveBeenCalled();
expect(after).not.toHaveBeenCalled();
}) },
queueableFn = {
fn: jasmine.createSpy('test body').and.callFake(function() {
expect(before).toHaveBeenCalled();
expect(after).not.toHaveBeenCalled();
})
},
spec = new jasmineUnderTest.Spec({
queueableFn: queueableFn,
beforeAndAfterFns: function() {
return {befores: [before], afters: [after]}
return { befores: [before], afters: [after] };
},
queueRunnerFactory: fakeQueueRunner
});
@@ -104,8 +117,12 @@ describe("Spec", function() {
spec.execute();
var options = fakeQueueRunner.calls.mostRecent().args[0];
expect(options.queueableFns).toEqual([before, queueableFn]);
expect(options.cleanupFns).toEqual([after]);
expect(options.queueableFns).toEqual([
{ fn: jasmine.any(Function) },
before,
queueableFn
]);
expect(options.cleanupFns).toEqual([after, { fn: jasmine.any(Function) }]);
});
it("tells the queue runner that it's a leaf node", function() {
@@ -113,21 +130,22 @@ describe("Spec", function() {
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
beforeAndAfterFns: function() {
return {befores: [], afters: []}
return { befores: [], afters: [] };
},
queueRunnerFactory: fakeQueueRunner
});
spec.execute();
expect(fakeQueueRunner).toHaveBeenCalledWith(jasmine.objectContaining({
isLeaf: true
}));
expect(fakeQueueRunner).toHaveBeenCalledWith(
jasmine.objectContaining({
isLeaf: true
})
);
});
it("is marked pending if created without a function body", function() {
it('is marked pending if created without a function body', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
@@ -140,67 +158,48 @@ describe("Spec", function() {
expect(spec.status()).toBe('pending');
});
it("can be disabled, but still calls callbacks", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
.and.callFake(function(attrs) { attrs.onComplete(); }),
it('can be excluded 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 jasmineUnderTest.Spec({
onStart:startCallback,
onStart: startCallback,
queueableFn: { fn: specBody },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
spec.disable();
spec.execute('cally-back', true);
expect(spec.status()).toBe('disabled');
spec.execute();
expect(fakeQueueRunner).toHaveBeenCalled();
expect(fakeQueueRunner).toHaveBeenCalledWith(
jasmine.objectContaining({
onComplete: jasmine.any(Function),
queueableFns: [{ fn: jasmine.any(Function) }],
cleanupFns: [{ fn: jasmine.any(Function) }]
})
);
expect(specBody).not.toHaveBeenCalled();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
args.cleanupFns[0].fn();
expect(resultCallback).toHaveBeenCalled();
expect(spec.result.status).toBe('excluded');
});
it("can be disabled at execution time by a parent", function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner')
.and.callFake(function(attrs) { attrs.onComplete(); }),
startCallback = jasmine.createSpy('startCallback'),
specBody = jasmine.createSpy('specBody'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
onStart:startCallback,
queueableFn: { fn: specBody },
resultCallback: resultCallback,
queueRunnerFactory: fakeQueueRunner
});
spec.execute(undefined, false);
expect(spec.result.status).toBe('disabled');
expect(fakeQueueRunner).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')
.and.callFake(function(attrs) { attrs.onComplete(); }),
it('can be marked pending, but still calls callbacks when executed', function() {
var fakeQueueRunner = jasmine.createSpy('fakeQueueRunner'),
startCallback = jasmine.createSpy('startCallback'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
onStart: startCallback,
resultCallback: resultCallback,
description: "with a spec",
description: 'with a spec',
getSpecName: function() {
return "a suite with a spec"
return 'a suite with a spec';
},
queueRunnerFactory: fakeQueueRunner,
queueableFn: { fn: null }
@@ -214,25 +213,38 @@ describe("Spec", function() {
expect(fakeQueueRunner).toHaveBeenCalled();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.queueableFns[0].fn();
expect(startCallback).toHaveBeenCalled();
expect(resultCallback).toHaveBeenCalledWith({
id: spec.id,
status: 'pending',
description: 'with a spec',
fullName: 'a suite with a spec',
failedExpectations: [],
passedExpectations: [],
pendingReason: ''
});
args.cleanupFns[0].fn('things');
expect(resultCallback).toHaveBeenCalledWith(
{
id: spec.id,
status: 'pending',
description: 'with a spec',
fullName: 'a suite with a spec',
failedExpectations: [],
passedExpectations: [],
deprecationWarnings: [],
pendingReason: '',
duration: jasmine.any(Number),
properties: null
},
'things'
);
});
it("should call the done callback on execution complete", function() {
it('should call the done callback on execution complete', function() {
var done = jasmine.createSpy('done callback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
catchExceptions: function() { return false; },
catchExceptions: function() {
return false;
},
resultCallback: function() {},
queueRunnerFactory: function(attrs) { attrs.onComplete(); }
queueRunnerFactory: function(attrs) {
attrs.onComplete();
}
});
spec.execute(done);
@@ -240,30 +252,104 @@ describe("Spec", function() {
expect(done).toHaveBeenCalled();
});
it("#status returns passing by default", function() {
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
it('should call the done callback with an error if the spec is failed', function() {
var done = jasmine.createSpy('done callback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
catchExceptions: function() {
return false;
},
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
spec.result.status = 'failed';
attrs.onComplete();
}
});
spec.execute(done);
expect(done).toHaveBeenCalledWith(
jasmine.any(jasmineUnderTest.StopExecutionError)
);
});
it('should report the duration of the test', function() {
var timer = jasmine.createSpyObj('timer', { start: null, elapsed: 77000 }),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') },
catchExceptions: function() {
return false;
},
resultCallback: function(result) {
duration = result.duration;
},
queueRunnerFactory: function(config) {
config.queueableFns.forEach(function(qf) {
qf.fn();
});
config.cleanupFns.forEach(function(qf) {
qf.fn();
});
config.onComplete();
},
timer: timer
}),
duration = undefined;
spec.execute(function() {});
expect(duration).toBe(77000);
});
it('should report properties set during the test', function() {
var done = jasmine.createSpy('done callback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') },
catchExceptions: function() {
return false;
},
resultCallback: function() {},
queueRunnerFactory: function(attrs) {
attrs.onComplete();
}
});
spec.setSpecProperty('a', 4);
spec.execute(done);
expect(spec.result.properties).toEqual({ a: 4 });
});
it('#status returns passing by default', function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') }
});
expect(spec.status()).toBe('passed');
});
it("#status returns passed if all expectations in the spec have passed", function() {
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body")} });
it('#status returns passed if all expectations in the spec have passed', function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') }
});
spec.addExpectationResult(true);
expect(spec.status()).toBe('passed');
});
it("#status returns failed if any expectations in the spec have failed", function() {
var spec = new jasmineUnderTest.Spec({queueableFn: { fn: jasmine.createSpy("spec body") } });
it('#status returns failed if any expectations in the spec have failed', function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy('spec body') }
});
spec.addExpectationResult(true);
spec.addExpectationResult(false);
expect(spec.status()).toBe('failed');
});
it("keeps track of passed and failed expectations", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
it('keeps track of passed and failed expectations', function() {
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: jasmine.createSpy("spec body") },
expectationResultFactory: function (data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
queueableFn: { fn: jasmine.createSpy('spec body') },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.addExpectationResult(true, 'expectation1');
@@ -271,37 +357,54 @@ describe("Spec", function() {
spec.execute();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['expectation1']);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['expectation2']);
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual([
'expectation1'
]);
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'),
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
spec.addExpectationResult(true, 'passed');
expect(function() {
spec.addExpectationResult(false, 'failed')
spec.addExpectationResult(false, 'failed');
}).toThrowError(jasmineUnderTest.errors.ExpectationFailed);
spec.execute();
expect(resultCallback.calls.first().args[0].passedExpectations).toEqual(['passed']);
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual(['failed']);
fakeQueueRunner.calls.mostRecent().args[0].cleanupFns[0].fn();
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() {
it('does not throw an ExpectationFailed error when handling an error', function() {
var resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: function(attrs) {
attrs.onComplete();
},
resultCallback: resultCallback,
throwOnExpectationFailure: true
});
@@ -309,8 +412,10 @@ describe("Spec", function() {
spec.onException('failing exception');
});
it("can return its full name", function() {
var specNameSpy = jasmine.createSpy('specNameSpy').and.returnValue('expected val');
it('can return its full name', function() {
var specNameSpy = jasmine
.createSpy('specNameSpy')
.and.returnValue('expected val');
var spec = new jasmineUnderTest.Spec({
getSpecName: specNameSpy,
@@ -321,121 +426,94 @@ describe("Spec", function() {
expect(specNameSpy.calls.mostRecent().args[0].id).toEqual(spec.id);
});
describe("when a spec is marked pending during execution", function() {
it("should mark the spec as pending", 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(jasmineUnderTest.Spec.pendingSpecExceptionMessage));
opts.onException(
new Error(jasmineUnderTest.Spec.pendingSpecExceptionMessage)
);
},
spec = new jasmineUnderTest.Spec({
description: 'my test',
id: 'some-id',
queueableFn: { fn: function() { } },
queueableFn: { fn: function() {} },
queueRunnerFactory: fakeQueueRunner
});
spec.execute();
expect(spec.status()).toEqual("pending");
expect(spec.status()).toEqual('pending');
expect(spec.result.pendingReason).toEqual('');
});
it("should set the pendingReason", function() {
it('should set the pendingReason', function() {
var fakeQueueRunner = function(opts) {
opts.onException(new Error(jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'custom message'));
opts.onException(
new Error(
jasmineUnderTest.Spec.pendingSpecExceptionMessage +
'custom message'
)
);
},
spec = new jasmineUnderTest.Spec({
description: 'my test',
id: 'some-id',
queueableFn: { fn: function() { } },
queueableFn: { fn: function() {} },
queueRunnerFactory: fakeQueueRunner
});
spec.execute();
expect(spec.status()).toEqual("pending");
expect(spec.status()).toEqual('pending');
expect(spec.result.pendingReason).toEqual('custom message');
});
});
it("should log a failure when handling an exception", function() {
var resultCallback = jasmine.createSpy('resultCallback'),
it('should log a failure when handling an exception', function() {
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.onException('foo');
spec.execute();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([{
error: 'foo',
matcherName: '',
passed: false,
expected: '',
actual: ''
}]);
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.cleanupFns[0].fn();
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'),
it('should not log an additional failure when handling an ExpectationFailed error', function() {
var fakeQueueRunner = jasmine.createSpy('queueRunner'),
resultCallback = jasmine.createSpy('resultCallback'),
spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} },
expectationResultFactory: function(data) { return data; },
queueRunnerFactory: function(attrs) { attrs.onComplete(); },
expectationResultFactory: function(data) {
return data;
},
queueRunnerFactory: fakeQueueRunner,
resultCallback: resultCallback
});
spec.onException(new jasmineUnderTest.errors.ExpectationFailed());
spec.execute();
var args = fakeQueueRunner.calls.mostRecent().args[0];
args.cleanupFns[0].fn();
expect(resultCallback.calls.first().args[0].failedExpectations).toEqual([]);
});
it("retrieves a result with updated status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
expect(spec.getResult().status).toBe('passed');
});
it("retrives a result with disabled status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
spec.disable();
expect(spec.getResult().status).toBe('disabled');
});
it("retrives a result with pending status", function() {
var spec = new jasmineUnderTest.Spec({ queueableFn: { fn: function() {} } });
spec.pend();
expect(spec.getResult().status).toBe('pending');
});
it("should not be executable when disabled", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
spec.disable();
expect(spec.isExecutable()).toBe(false);
});
it("should be executable when pending", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
spec.pend();
expect(spec.isExecutable()).toBe(true);
});
it("should be executable when not disabled or pending", function() {
var spec = new jasmineUnderTest.Spec({
queueableFn: { fn: function() {} }
});
expect(spec.isExecutable()).toBe(true);
});
});

View File

@@ -1,29 +1,35 @@
describe("SpyRegistry", function() {
describe("#spyOn", function() {
it("checks for the existence of the object", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
describe('SpyRegistry', function() {
function createSpy(name, originalFn) {
return jasmineUnderTest.Spy(name, originalFn);
}
describe('#spyOn', function() {
it('checks for the existence of the object', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
});
expect(function() {
spyRegistry.spyOn(void 0, 'pants');
}).toThrowError(/could not find an object/);
});
it("checks that a method name was passed", function() {
it('checks that a method name was passed', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
expect(function() {
spyRegistry.spyOn(subject);
}).toThrowError(/No method name supplied/);
expect(function() {
spyRegistry.spyOn(subject);
}).toThrowError(/No method name supplied/);
});
it("checks that the object is not `null`", function() {
it('checks that the object is not `null`', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
expect(function() {
spyRegistry.spyOn(null, 'pants');
}).toThrowError(/could not find an object/);
});
it("checks that the method name is not `null`", function() {
it('checks that the method name is not `null`', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
@@ -32,7 +38,7 @@ describe("SpyRegistry", function() {
}).toThrowError(/No method name supplied/);
});
it("checks for the existence of the method", function() {
it('checks for the existence of the method', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
@@ -41,9 +47,14 @@ describe("SpyRegistry", function() {
}).toThrowError(/method does not exist/);
});
it("checks if it has already been spied upon", function() {
it('checks if it has already been spied upon', function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
subject = { spiedFunc: function() {} };
spyRegistry.spyOn(subject, 'spiedFunc');
@@ -53,10 +64,7 @@ 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; }
it('checks if it can be spied upon', function() {
var scope = {};
function myFunc() {
@@ -70,7 +78,11 @@ describe("SpyRegistry", function() {
});
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
}
}),
subject = { spiedFunc: scope.myFunc };
expect(function() {
@@ -82,38 +94,43 @@ describe("SpyRegistry", function() {
}).not.toThrowError(/is not declared writable or has no setter/);
});
it("overrides the method on the object and returns the spy", function() {
it('overrides the method on the object and returns the spy', function() {
var originalFunctionWasCalled = false,
spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = { spiedFunc: function() { originalFunctionWasCalled = true; } };
spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
}),
subject = {
spiedFunc: function() {
originalFunctionWasCalled = true;
}
};
var spy = spyRegistry.spyOn(subject, 'spiedFunc');
expect(subject.spiedFunc).toEqual(spy);
subject.spiedFunc();
expect(originalFunctionWasCalled).toBe(false);
});
});
describe("#spyOnProperty", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
it("checks for the existence of the object", function() {
describe('#spyOnProperty', function() {
it('checks for the existence of the object', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
expect(function() {
spyRegistry.spyOnProperty(void 0, 'pants');
}).toThrowError(/could not find an object/);
});
it("checks that a property name was passed", function() {
it('checks that a property name was passed', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
expect(function() {
spyRegistry.spyOnProperty(subject);
}).toThrowError(/No property name supplied/);
expect(function() {
spyRegistry.spyOnProperty(subject);
}).toThrowError(/No property name supplied/);
});
it("checks for the existence of the method", function() {
it('checks for the existence of the method', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
@@ -122,12 +139,14 @@ describe("SpyRegistry", function() {
}).toThrowError(/property does not exist/);
});
it("checks for the existence of access type", function() {
it('checks for the existence of access type', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
Object.defineProperty(subject, 'pants', {
get: function() { return 1; },
get: function() {
return 1;
},
configurable: true
});
@@ -136,23 +155,7 @@ describe("SpyRegistry", function() {
}).toThrowError(/does not have access type/);
});
it("checks if it has already been spied upon", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
subject = {};
Object.defineProperty(subject, 'spiedProp', {
get: function() { return 1; },
configurable: true
});
spyRegistry.spyOnProperty(subject, 'spiedProp');
expect(function() {
spyRegistry.spyOnProperty(subject, 'spiedProp');
}).toThrowError(/has already been spied upon/);
});
it("checks if it can be spied upon", function() {
it('checks if it can be spied upon', function() {
var subject = {};
Object.defineProperty(subject, 'myProp', {
@@ -175,48 +178,363 @@ describe("SpyRegistry", function() {
}).not.toThrowError(/is not declared configurable/);
});
it("overrides the property getter on the object and returns the spy", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
it('overrides the property getter on the object and returns the spy', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
}),
subject = {},
returnValue = 1;
Object.defineProperty(subject, 'spiedProperty', {
get: function() { return returnValue; },
get: function() {
return returnValue;
},
configurable: true
});
expect(subject.spiedProperty).toEqual(returnValue);
var spy = spyRegistry.spyOnProperty(subject, 'spiedProperty');
var getter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty').get;
var getter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty')
.get;
expect(getter).toEqual(spy);
expect(subject.spiedProperty).toBeUndefined();
});
it("overrides the property setter on the object and returns the spy", function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry(),
it('overrides the property setter on the object and returns the spy', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
}),
subject = {},
returnValue = 1;
Object.defineProperty(subject, 'spiedProperty', {
get: function() { return returnValue; },
get: function() {
return returnValue;
},
set: function() {},
configurable: true
});
var spy = spyRegistry.spyOnProperty(subject, 'spiedProperty', 'set');
var setter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty').set;
var setter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty')
.set;
expect(subject.spiedProperty).toEqual(returnValue);
expect(setter).toEqual(spy);
});
describe('when the property is already spied upon', function() {
it('throws an error if respy is not allowed', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
}),
subject = {};
Object.defineProperty(subject, 'spiedProp', {
get: function() {
return 1;
},
configurable: true
});
spyRegistry.spyOnProperty(subject, 'spiedProp');
expect(function() {
spyRegistry.spyOnProperty(subject, 'spiedProp');
}).toThrowError(/spiedProp#get has already been spied upon/);
});
it('returns the original spy if respy is allowed', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: createSpy
}),
subject = {};
spyRegistry.allowRespy(true);
Object.defineProperty(subject, 'spiedProp', {
get: function() {
return 1;
},
configurable: true
});
var originalSpy = spyRegistry.spyOnProperty(subject, 'spiedProp');
expect(spyRegistry.spyOnProperty(subject, 'spiedProp')).toBe(
originalSpy
);
});
});
});
describe("#clearSpies", function() {
it("restores the original functions on the spied-upon objects", function() {
describe('#spyOnAllFunctions', function() {
it('checks for the existence of the object', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry();
expect(function() {
spyRegistry.spyOnAllFunctions(void 0);
}).toThrowError(/spyOnAllFunctions could not find an object to spy upon/);
});
it('overrides all writable and configurable functions of the object and its parents', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var createNoop = function() {
return function() {
/**/
};
};
var noop1 = createNoop();
var noop2 = createNoop();
var noop3 = createNoop();
var noop4 = createNoop();
var noop5 = createNoop();
var parent = {
parentSpied1: noop1
};
var subject = Object.create(parent);
Object.defineProperty(subject, 'spied1', {
value: noop1,
writable: true,
configurable: true,
enumerable: true
});
Object.defineProperty(subject, 'spied2', {
value: noop2,
writable: true,
configurable: true,
enumerable: true
});
var _spied3 = noop3;
Object.defineProperty(subject, 'spied3', {
configurable: true,
set: function(val) {
_spied3 = val;
},
get: function() {
return _spied3;
},
enumerable: true
});
subject.spied4 = noop4;
Object.defineProperty(subject, 'notSpied2', {
value: noop2,
writable: false,
configurable: true,
enumerable: true
});
Object.defineProperty(subject, 'notSpied3', {
value: noop3,
writable: true,
configurable: false,
enumerable: true
});
Object.defineProperty(subject, 'notSpied4', {
configurable: false,
set: function(val) {
/**/
},
get: function() {
return noop4;
},
enumerable: true
});
Object.defineProperty(subject, 'notSpied5', {
value: noop5,
writable: true,
configurable: true,
enumerable: false
});
subject.notSpied6 = 6;
var spiedObject = spyRegistry.spyOnAllFunctions(subject);
expect(subject.parentSpied1).toBe('I am a spy');
expect(subject.notSpied2).toBe(noop2);
expect(subject.notSpied3).toBe(noop3);
expect(subject.notSpied4).toBe(noop4);
expect(subject.notSpied5).toBe(noop5);
expect(subject.notSpied6).toBe(6);
expect(subject.spied1).toBe('I am a spy');
expect(subject.spied2).toBe('I am a spy');
expect(subject.spied3).toBe('I am a spy');
expect(subject.spied4).toBe('I am a spy');
expect(spiedObject).toBe(subject);
});
it('overrides prototype methods on the object', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var noop1 = function() {};
var noop2 = function() {};
var MyClass = function() {
this.spied1 = noop1;
};
MyClass.prototype.spied2 = noop2;
var subject = new MyClass();
spyRegistry.spyOnAllFunctions(subject);
expect(subject.spied1).toBe('I am a spy');
expect(subject.spied2).toBe('I am a spy');
expect(MyClass.prototype.spied2).toBe(noop2);
});
it('does not override non-enumerable properties (like Object.prototype methods)', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = {
spied1: function() {}
};
spyRegistry.spyOnAllFunctions(subject);
expect(subject.spied1).toBe('I am a spy');
expect(subject.toString).not.toBe('I am a spy');
expect(subject.hasOwnProperty).not.toBe('I am a spy');
});
describe('when includeNonEnumerable is true', function() {
it('does not override Object.prototype methods', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = {
spied1: function() {}
};
spyRegistry.spyOnAllFunctions(subject, true);
expect(subject.spied1).toBe('I am a spy');
expect(subject.toString).not.toBe('I am a spy');
expect(subject.hasOwnProperty).not.toBe('I am a spy');
});
it('overrides non-enumerable properties', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = {
spied1: function() {},
spied2: function() {}
};
Object.defineProperty(subject, 'spied2', {
enumerable: false,
writable: true,
configurable: true
});
spyRegistry.spyOnAllFunctions(subject, true);
expect(subject.spied1).toBe('I am a spy');
expect(subject.spied2).toBe('I am a spy');
});
it('should not spy on non-enumerable functions named constructor', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = {
constructor: function() {}
};
Object.defineProperty(subject, 'constructor', {
enumerable: false,
writable: true,
configurable: true
});
spyRegistry.spyOnAllFunctions(subject, true);
expect(subject.constructor).not.toBe('I am a spy');
});
it('should spy on enumerable functions named constructor', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = {
constructor: function() {}
};
spyRegistry.spyOnAllFunctions(subject, true);
expect(subject.constructor).toBe('I am a spy');
});
it('should not throw an exception if we try and access strict mode restricted properties', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subject = function() {};
var fn = function() {
spyRegistry.spyOnAllFunctions(subject, true);
};
expect(fn).not.toThrow();
});
it('should not spy on properties which are more permissable further up the prototype chain', function() {
var spyRegistry = new jasmineUnderTest.SpyRegistry({
createSpy: function() {
return 'I am a spy';
}
});
var subjectParent = Object.defineProperty({}, 'sharedProp', {
value: function() {},
writable: true,
configurable: true
});
var subject = Object.create(subjectParent);
Object.defineProperty(subject, 'sharedProp', {
value: function() {}
});
var fn = function() {
spyRegistry.spyOnAllFunctions(subject, true);
};
expect(fn).not.toThrow();
expect(subject).not.toBe('I am a spy');
});
});
});
describe('#clearSpies', function() {
it('restores the original functions on the spied-upon objects', function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalFunction = function() {},
subject = { spiedFunc: originalFunction };
@@ -226,9 +544,14 @@ describe("SpyRegistry", function() {
expect(subject.spiedFunc).toBe(originalFunction);
});
it("restores the original functions, even when that spy has been replace and re-spied upon", function() {
it('restores the original functions, even when that spy has been replace and re-spied upon', function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalFunction = function() {},
subject = { spiedFunc: originalFunction };
@@ -246,13 +569,15 @@ describe("SpyRegistry", function() {
});
it("does not add a property that the spied-upon object didn't originally have", function() {
// IE 8 doesn't support `Object.create`
if (jasmine.getEnv().ieVersion < 9) { return; }
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalFunction = function() {},
subjectParent = {spiedFunc: originalFunction};
subjectParent = { spiedFunc: originalFunction };
var subject = Object.create(subjectParent);
@@ -265,14 +590,16 @@ describe("SpyRegistry", function() {
expect(subject.spiedFunc).toBe(originalFunction);
});
it("restores the original function when it\'s inherited and cannot be deleted", function() {
// IE 8 doesn't support `Object.create` or `Object.defineProperty`
if (jasmine.getEnv().ieVersion < 9) { return; }
it("restores the original function when it's inherited and cannot be deleted", function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalFunction = function() {},
subjectParent = {spiedFunc: originalFunction};
subjectParent = { spiedFunc: originalFunction };
var subject = Object.create(subjectParent);
@@ -288,15 +615,17 @@ describe("SpyRegistry", function() {
expect(jasmineUnderTest.isSpy(subject.spiedFunc)).toBe(false);
});
it("restores window.onerror by overwriting, not deleting", function() {
function FakeWindow() {
}
it('restores window.onerror by overwriting, not deleting', function() {
function FakeWindow() {}
FakeWindow.prototype.onerror = function() {};
var spies = [],
global = new FakeWindow(),
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() { return spies; },
currentSpies: function() {
return spies;
},
createSpy: createSpy,
global: global
});
@@ -307,50 +636,58 @@ describe("SpyRegistry", function() {
});
});
describe('spying on properties', function() {
it("restores the original properties on the spied-upon objects", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
describe('spying on properties', function() {
it('restores the original properties on the spied-upon objects', function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalReturn = 1,
subject = {};
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
originalReturn = 1,
subject = {};
Object.defineProperty(subject, 'spiedProp', {
get: function() { return originalReturn; },
configurable: true
});
spyRegistry.spyOnProperty(subject, 'spiedProp');
spyRegistry.clearSpies();
expect(subject.spiedProp).toBe(originalReturn);
Object.defineProperty(subject, 'spiedProp', {
get: function() {
return originalReturn;
},
configurable: true
});
it("does not add a property that the spied-upon object didn't originally have", function() {
// IE 8 doesn't support `Object.create`
if (jasmine.getEnv().ieVersion < 9) { return; }
spyRegistry.spyOnProperty(subject, 'spiedProp');
spyRegistry.clearSpies();
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({currentSpies: function() { return spies; }}),
originalReturn = 1,
subjectParent = {};
Object.defineProperty(subjectParent, 'spiedProp', {
get: function() { return originalReturn; },
configurable: true
});
var subject = Object.create(subjectParent);
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
spyRegistry.spyOnProperty(subject, 'spiedProp');
spyRegistry.clearSpies();
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
expect(subject.spiedProp).toBe(originalReturn);
});
expect(subject.spiedProp).toBe(originalReturn);
});
it("does not add a property that the spied-upon object didn't originally have", function() {
var spies = [],
spyRegistry = new jasmineUnderTest.SpyRegistry({
currentSpies: function() {
return spies;
},
createSpy: createSpy
}),
originalReturn = 1,
subjectParent = {};
Object.defineProperty(subjectParent, 'spiedProp', {
get: function() {
return originalReturn;
},
configurable: true
});
var subject = Object.create(subjectParent);
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
spyRegistry.spyOnProperty(subject, 'spiedProp');
spyRegistry.clearSpies();
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
expect(subject.spiedProp).toBe(originalReturn);
});
});
});

View File

@@ -1,46 +1,82 @@
describe('Spies', function () {
describe("createSpy", function() {
describe('Spies', function() {
var env;
beforeEach(function() {
env = new jasmineUnderTest.Env();
});
afterEach(function() {
env.cleanup_();
});
describe('createSpy', function() {
var TestClass;
beforeEach(function() {
TestClass = function() {};
TestClass.prototype.someFunction = function() {};
TestClass.prototype.someFunction.bob = "test";
TestClass.prototype.someFunction.bob = 'test';
});
it("preserves the properties of the spied function", function() {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
it('preserves the properties of the spied function', function() {
var spy = env.createSpy(
TestClass.prototype,
TestClass.prototype.someFunction
);
expect(spy.bob).toEqual("test");
expect(spy.bob).toEqual('test');
});
it("warns the user that we intend to overwrite an existing property", function() {
TestClass.prototype.someFunction.and = "turkey";
it('should allow you to omit the name argument and only pass the originalFn argument', function() {
var fn = function test() {};
var spy = env.createSpy(fn);
// IE doesn't do `.name`
if (fn.name === 'test') {
expect(spy.and.identity).toEqual('test');
} else {
expect(spy.and.identity).toEqual('unknown');
}
});
it('warns the user that we intend to overwrite an existing property', function() {
TestClass.prototype.someFunction.and = 'turkey';
expect(function() {
jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
}).toThrowError("Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon");
env.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
}).toThrowError(
"Jasmine spies would overwrite the 'and' and 'calls' properties on the object being spied upon"
);
});
it("adds a spyStrategy and callTracker to the spy", function() {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
it('adds a spyStrategy and callTracker to the spy', function() {
var spy = env.createSpy(
TestClass.prototype,
TestClass.prototype.someFunction
);
expect(spy.and).toEqual(jasmine.any(jasmineUnderTest.SpyStrategy));
expect(spy.calls).toEqual(jasmine.any(jasmineUnderTest.CallTracker));
});
it("tracks the argument of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
it('tracks the argument of calls', function() {
var spy = env.createSpy(
TestClass.prototype,
TestClass.prototype.someFunction
);
var trackSpy = spyOn(spy.calls, 'track');
spy("arg");
spy('arg');
expect(trackSpy.calls.mostRecent().args[0].args).toEqual(["arg"]);
expect(trackSpy.calls.mostRecent().args[0].args).toEqual(['arg']);
});
it("tracks the context of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
it('tracks the context of calls', function() {
var spy = env.createSpy(
TestClass.prototype,
TestClass.prototype.someFunction
);
var trackSpy = spyOn(spy.calls, 'track');
var contextObject = { spyMethod: spy };
contextObject.spyMethod();
@@ -48,80 +84,218 @@ describe('Spies', function () {
expect(trackSpy.calls.mostRecent().args[0].object).toEqual(contextObject);
});
it("tracks the return value of calls", function () {
var spy = jasmineUnderTest.createSpy(TestClass.prototype, TestClass.prototype.someFunction);
var trackSpy = spyOn(spy.calls, "track");
it('tracks the return value of calls', function() {
var spy = env.createSpy(
TestClass.prototype,
TestClass.prototype.someFunction
);
var trackSpy = spyOn(spy.calls, 'track');
spy.and.returnValue("return value");
spy.and.returnValue('return value');
spy();
expect(trackSpy.calls.mostRecent().args[0].returnValue).toEqual("return value");
expect(trackSpy.calls.mostRecent().args[0].returnValue).toEqual(
'return value'
);
});
it("preserves arity of original function", function () {
it('preserves arity of original function', function() {
var functions = [
function nullary () {},
function unary (arg) {},
function binary (arg1, arg2) {},
function ternary (arg1, arg2, arg3) {},
function quaternary (arg1, arg2, arg3, arg4) {},
function quinary (arg1, arg2, arg3, arg4, arg5) {},
function senary (arg1, arg2, arg3, arg4, arg5, arg6) {}
function nullary() {},
function unary(arg) {},
function binary(arg1, arg2) {},
function ternary(arg1, arg2, arg3) {},
function quaternary(arg1, arg2, arg3, arg4) {},
function quinary(arg1, arg2, arg3, arg4, arg5) {},
function senary(arg1, arg2, arg3, arg4, arg5, arg6) {}
];
for (var arity = 0; arity < functions.length; arity++) {
var someFunction = functions[arity],
spy = jasmineUnderTest.createSpy(someFunction.name, someFunction);
spy = env.createSpy(someFunction.name, someFunction);
expect(spy.length).toEqual(arity);
}
});
});
describe("createSpyObj", function() {
it("should create an object with spy methods and corresponding return values when you call jasmine.createSpyObj() with an object", function () {
var spyObj = jasmineUnderTest.createSpyObj('BaseName', {'method1': 42, 'method2': 'special sauce' });
describe('createSpyObj', function() {
it('should create an object with spy methods and corresponding return values when you call jasmine.createSpyObj() with an object', function() {
var spyObj = env.createSpyObj('BaseName', {
method1: 42,
method2: 'special sauce'
});
expect(spyObj.method1()).toEqual(42);
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
expect(spyObj.method2()).toEqual('special sauce');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
});
it('should create an object with a bunch of spy methods when you call jasmine.createSpyObj()', function() {
var spyObj = env.createSpyObj('BaseName', ['method1', 'method2']);
it("should create an object with a bunch of spy methods when you call jasmine.createSpyObj()", function() {
var spyObj = jasmineUnderTest.createSpyObj('BaseName', ['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity()).toEqual('BaseName.method2');
expect(spyObj).toEqual({
method1: jasmine.any(Function),
method2: jasmine.any(Function)
});
expect(spyObj.method1.and.identity).toEqual('BaseName.method1');
expect(spyObj.method2.and.identity).toEqual('BaseName.method2');
});
it("should allow you to omit the baseName", function() {
var spyObj = jasmineUnderTest.createSpyObj(['method1', 'method2']);
it('should allow you to omit the baseName', function() {
var spyObj = env.createSpyObj(['method1', 'method2']);
expect(spyObj).toEqual({ method1: jasmine.any(Function), method2: jasmine.any(Function)});
expect(spyObj.method1.and.identity()).toEqual('unknown.method1');
expect(spyObj.method2.and.identity()).toEqual('unknown.method2');
expect(spyObj).toEqual({
method1: jasmine.any(Function),
method2: jasmine.any(Function)
});
expect(spyObj.method1.and.identity).toEqual('unknown.method1');
expect(spyObj.method2.and.identity).toEqual('unknown.method2');
});
it("should throw if you do not pass an array or object argument", function() {
it('should throw if you do not pass an array or object argument', function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName');
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
env.createSpyObj('BaseName');
}).toThrow(
'createSpyObj requires a non-empty array or object of method names to create spies for'
);
});
it("should throw if you pass an empty array argument", function() {
it('should throw if you pass an empty array argument', function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName', []);
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
env.createSpyObj('BaseName', []);
}).toThrow(
'createSpyObj requires a non-empty array or object of method names to create spies for'
);
});
it("should throw if you pass an empty object argument", function() {
it('should throw if you pass an empty object argument', function() {
expect(function() {
jasmineUnderTest.createSpyObj('BaseName', {});
}).toThrow("createSpyObj requires a non-empty array or object of method names to create spies for");
env.createSpyObj('BaseName', {});
}).toThrow(
'createSpyObj requires a non-empty array or object of method names to create spies for'
);
});
it('creates an object with spy properties if a second list is passed', function() {
var spyObj = env.createSpyObj('base', ['method1'], ['prop1']);
expect(spyObj).toEqual({
method1: jasmine.any(Function),
prop1: undefined
});
var descriptor = Object.getOwnPropertyDescriptor(spyObj, 'prop1');
expect(descriptor.get.and.identity).toEqual('base.prop1.get');
expect(descriptor.set.and.identity).toEqual('base.prop1.set');
});
it('creates an object with property names and return values if second object is passed', function() {
var spyObj = env.createSpyObj('base', ['method1'], {
prop1: 'foo',
prop2: 37
});
expect(spyObj).toEqual({
method1: jasmine.any(Function),
prop1: 'foo',
prop2: 37
});
expect(spyObj.prop1).toEqual('foo');
expect(spyObj.prop2).toEqual(37);
spyObj.prop2 = 4;
expect(spyObj.prop2).toEqual(37);
expect(
Object.getOwnPropertyDescriptor(spyObj, 'prop2').set.calls.count()
).toBe(1);
});
it('allows base name to be omitted when assigning methods and properties', function() {
var spyObj = env.createSpyObj({ m: 3 }, { p: 4 });
expect(spyObj.m()).toEqual(3);
expect(spyObj.p).toEqual(4);
expect(
Object.getOwnPropertyDescriptor(spyObj, 'p').get.and.identity
).toEqual('unknown.p.get');
});
});
it('can use different strategies for different arguments', function() {
var spy = env.createSpy('foo');
spy.and.returnValue(42);
spy.withArgs('baz', 'grault').and.returnValue(-1);
spy.withArgs('thud').and.returnValue('bob');
expect(spy('foo')).toEqual(42);
expect(spy('baz', 'grault')).toEqual(-1);
expect(spy('thud')).toEqual('bob');
expect(spy('baz', 'grault', 'waldo')).toEqual(42);
});
it('uses custom equality testers when selecting a strategy', function() {
var spy = env.createSpy('foo');
spy.and.returnValue(42);
spy.withArgs(jasmineUnderTest.any(String)).and.returnValue(-1);
expect(spy('foo')).toEqual(-1);
expect(spy({})).toEqual(42);
});
it('can reconfigure an argument-specific strategy', function() {
var spy = env.createSpy('foo');
spy.withArgs('foo').and.returnValue(42);
spy.withArgs('foo').and.returnValue(17);
expect(spy('foo')).toEqual(17);
});
describe('any promise-based strategy', function() {
it('works with global Promise library when available', function(done) {
jasmine.getEnv().requirePromises();
var spy = env.createSpy('foo').and.resolveTo(42);
spy()
.then(function(result) {
expect(result).toEqual(42);
done();
})
.catch(done.fail);
});
it('works with a custom Promise library', function() {
var customPromise = {
resolve: jasmine.createSpy(),
reject: jasmine.createSpy()
};
customPromise.resolve.and.returnValue('resolved');
env.configure({ Promise: customPromise });
var spy = env.createSpy('foo').and.resolveTo(42);
expect(spy()).toEqual('resolved');
expect(customPromise.resolve).toHaveBeenCalledWith(42);
});
});
describe('when withArgs is used without a base strategy', function() {
it('uses the matching strategy', function() {
var spy = env.createSpy('foo');
spy.withArgs('baz').and.returnValue(-1);
expect(spy('baz')).toEqual(-1);
});
it("throws if the args don't match", function() {
var spy = env.createSpy('foo');
spy.withArgs('bar').and.returnValue(-1);
expect(function() {
spy('baz', { qux: 42 });
}).toThrowError(
"Spy 'foo' received a call with arguments [ 'baz', Object({ qux: 42 }) ] but all configured strategies specify other arguments."
);
});
});
});

View File

@@ -1,20 +1,19 @@
describe("SpyStrategy", function() {
it("defaults its name to unknown", function() {
describe('SpyStrategy', function() {
it('defaults its name to unknown', function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy();
expect(spyStrategy.identity()).toEqual("unknown");
expect(spyStrategy.identity).toEqual('unknown');
});
it("takes a name", function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy({name: "foo"});
it('takes a name', function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy({ name: 'foo' });
expect(spyStrategy.identity()).toEqual("foo");
expect(spyStrategy.identity).toEqual('foo');
});
it("stubs an original function, if provided", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn});
it('stubs an original function, if provided', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.exec();
@@ -22,22 +21,22 @@ describe("SpyStrategy", function() {
});
it("allows an original function to be called, passed through the params and returns it's value", function() {
var originalFn = jasmine.createSpy("original").and.returnValue(42),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
returnValue;
var originalFn = jasmine.createSpy('original').and.returnValue(42),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }),
returnValue;
spyStrategy.callThrough();
returnValue = spyStrategy.exec("foo");
returnValue = spyStrategy.exec(null, ['foo']);
expect(originalFn).toHaveBeenCalled();
expect(originalFn.calls.mostRecent().args).toEqual(["foo"]);
expect(originalFn.calls.mostRecent().args).toEqual(['foo']);
expect(returnValue).toEqual(42);
});
it("can return a specified value when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
returnValue;
it('can return a specified value when executed', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }),
returnValue;
spyStrategy.returnValue(17);
returnValue = spyStrategy.exec();
@@ -46,9 +45,9 @@ describe("SpyStrategy", function() {
expect(returnValue).toEqual(17);
});
it("can return specified values in order specified when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn});
it('can return specified values in order specified when executed', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.returnValues('value1', 'value2', 'value3');
@@ -59,31 +58,47 @@ describe("SpyStrategy", function() {
expect(originalFn).not.toHaveBeenCalled();
});
it("allows an exception to be thrown when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn});
it('allows an exception to be thrown when executed', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.throwError(new TypeError("bar"));
spyStrategy.throwError(new TypeError('bar'));
expect(function() { spyStrategy.exec(); }).toThrowError(TypeError, "bar");
expect(function() {
spyStrategy.exec();
}).toThrowError(TypeError, 'bar');
expect(originalFn).not.toHaveBeenCalled();
});
it("allows a non-Error to be thrown, wrapping it into an exception when executed", function() {
var originalFn = jasmine.createSpy("original"),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn});
it('allows a string to be thrown, wrapping it into an exception when executed', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.throwError("bar");
spyStrategy.throwError('bar');
expect(function() { spyStrategy.exec(); }).toThrowError(Error, "bar");
expect(function() {
spyStrategy.exec();
}).toThrowError(Error, 'bar');
expect(originalFn).not.toHaveBeenCalled();
});
it("allows a fake function to be called instead", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.returnValue(67),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
returnValue;
it('allows a non-Error to be thrown when executed', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.throwError({ code: 'ESRCH' });
expect(function() {
spyStrategy.exec();
}).toThrow(jasmine.objectContaining({ code: 'ESRCH' }));
expect(originalFn).not.toHaveBeenCalled();
});
it('allows a fake function to be called instead', function() {
var originalFn = jasmine.createSpy('original'),
fakeFn = jasmine.createSpy('fake').and.returnValue(67),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }),
returnValue;
spyStrategy.callFake(fakeFn);
returnValue = spyStrategy.exec();
@@ -92,46 +107,249 @@ describe("SpyStrategy", function() {
expect(returnValue).toEqual(67);
});
it("allows a fake async function to be called instead", function(done) {
it('allows a fake async function to be called instead', function(done) {
jasmine.getEnv().requireAsyncAwait();
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.callFake(eval("async () => { return 67; }")),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
returnValue;
var originalFn = jasmine.createSpy('original'),
fakeFn = jasmine
.createSpy('fake')
.and.callFake(eval('async () => { return 67; }')),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyStrategy.callFake(fakeFn);
spyStrategy.exec().then(function (returnValue) {
expect(originalFn).not.toHaveBeenCalled();
expect(fakeFn).toHaveBeenCalled();
expect(returnValue).toEqual(67);
done();
}).catch(function (err) {
done.fail(err);
})
spyStrategy
.exec()
.then(function(returnValue) {
expect(originalFn).not.toHaveBeenCalled();
expect(fakeFn).toHaveBeenCalled();
expect(returnValue).toEqual(67);
done();
})
.catch(function(err) {
done.fail(err);
});
});
describe('#resolveTo', function() {
it('allows a resolved promise to be returned', function(done) {
jasmine.getEnv().requirePromises();
var originalFn = jasmine.createSpy('original'),
getPromise = function() {
return Promise;
},
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
getPromise: getPromise
});
spyStrategy.resolveTo(37);
spyStrategy
.exec()
.then(function(returnValue) {
expect(returnValue).toEqual(37);
done();
})
.catch(done.fail);
});
it('allows an empty resolved promise to be returned', function(done) {
jasmine.getEnv().requirePromises();
var originalFn = jasmine.createSpy('original'),
getPromise = function() {
return Promise;
},
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
getPromise: getPromise
});
spyStrategy.resolveTo();
spyStrategy
.exec()
.then(function(returnValue) {
expect(returnValue).toBe();
done();
})
.catch(done.fail);
});
it('fails if promises are not available', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
expect(function() {
spyStrategy.resolveTo(37);
}).toThrowError(
'resolveTo requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'
);
});
});
describe('#rejectWith', function() {
it('allows a rejected promise to be returned', function(done) {
jasmine.getEnv().requirePromises();
var originalFn = jasmine.createSpy('original'),
getPromise = function() {
return Promise;
},
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
getPromise: getPromise
});
spyStrategy.rejectWith(new Error('oops'));
spyStrategy
.exec()
.then(done.fail)
.catch(function(error) {
expect(error).toEqual(new Error('oops'));
done();
})
.catch(done.fail);
});
it('allows an empty rejected promise to be returned', function(done) {
jasmine.getEnv().requirePromises();
var originalFn = jasmine.createSpy('original'),
getPromise = function() {
return Promise;
},
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
getPromise: getPromise
});
spyStrategy.rejectWith();
spyStrategy
.exec()
.then(done.fail)
.catch(function(error) {
expect(error).toBe();
done();
})
.catch(done.fail);
});
it('allows a non-Error to be rejected', function(done) {
jasmine.getEnv().requirePromises();
var originalFn = jasmine.createSpy('original'),
getPromise = function() {
return Promise;
},
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
getPromise: getPromise
});
spyStrategy.rejectWith('oops');
spyStrategy
.exec()
.then(done.fail)
.catch(function(error) {
expect(error).toEqual('oops');
done();
})
.catch(done.fail);
});
it('fails if promises are not available', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
expect(function() {
spyStrategy.rejectWith(new Error('oops'));
}).toThrowError(
'rejectWith requires global Promise, or `Promise` configured with `jasmine.getEnv().configure()`'
);
});
});
it('allows a custom strategy to be used', function() {
var plan = jasmine
.createSpy('custom strategy')
.and.returnValue('custom strategy result'),
customStrategy = jasmine
.createSpy('custom strategy')
.and.returnValue(plan),
originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
customStrategies: {
doSomething: customStrategy
}
});
spyStrategy.doSomething(1, 2, 3);
expect(customStrategy).toHaveBeenCalledWith(1, 2, 3);
expect(spyStrategy.exec(null, ['some', 'args'])).toEqual(
'custom strategy result'
);
expect(plan).toHaveBeenCalledWith('some', 'args');
});
it("throws an error if a custom strategy doesn't return a function", function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: originalFn,
customStrategies: {
doSomething: function() {
return 'not a function';
}
}
});
expect(function() {
spyStrategy.doSomething(1, 2, 3);
}).toThrowError('Spy strategy must return a function');
});
it('does not allow custom strategies to overwrite existing methods', function() {
var spyStrategy = new jasmineUnderTest.SpyStrategy({
fn: function() {},
customStrategies: {
exec: function() {}
}
});
expect(spyStrategy.exec).toBe(jasmineUnderTest.SpyStrategy.prototype.exec);
});
it('throws an error when a non-function is passed to callFake strategy', function() {
var originalFn = jasmine.createSpy('original'),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
invalidFakes = [5, 'foo', {}, true, false, null, void 0, new Date(), /.*/];
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
spyOn(jasmineUnderTest, 'isFunction_').and.returnValue(false);
spyOn(jasmineUnderTest, 'isAsyncFunction_').and.returnValue(false);
expect(function () {
expect(function() {
spyStrategy.callFake(function() {});
}).toThrowError(/^Argument passed to callFake should be a function, got/);
expect(function () {
expect(function() {
spyStrategy.callFake(function() {});
}).toThrowError(/^Argument passed to callFake should be a function, got/);
});
it("allows a return to plan stubbing after another strategy", function() {
var originalFn = jasmine.createSpy("original"),
fakeFn = jasmine.createSpy("fake").and.returnValue(67),
spyStrategy = new jasmineUnderTest.SpyStrategy({fn: originalFn}),
returnValue;
it('allows generator functions to be passed to callFake strategy', function() {
jasmine.getEnv().requireGeneratorFunctions();
var generator = jasmine.getEnv().makeGeneratorFunction('yield "ok";'),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: function() {} });
spyStrategy.callFake(generator);
expect(spyStrategy.exec().next().value).toEqual('ok');
});
it('allows a return to plan stubbing after another strategy', function() {
var originalFn = jasmine.createSpy('original'),
fakeFn = jasmine.createSpy('fake').and.returnValue(67),
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn }),
returnValue;
spyStrategy.callFake(fakeFn);
returnValue = spyStrategy.exec();
@@ -145,10 +363,10 @@ describe("SpyStrategy", function() {
expect(returnValue).toEqual(void 0);
});
it("returns the spy after changing the strategy", function(){
it('returns the spy after changing the strategy', function() {
var spy = {},
spyFn = jasmine.createSpy('spyFn').and.returnValue(spy),
spyStrategy = new jasmineUnderTest.SpyStrategy({getSpy: spyFn});
spyFn = jasmine.createSpy('spyFn').and.returnValue(spy),
spyStrategy = new jasmineUnderTest.SpyStrategy({ getSpy: spyFn });
expect(spyStrategy.callThrough()).toBe(spy);
expect(spyStrategy.returnValue()).toBe(spy);

258
spec/core/StackTraceSpec.js Normal file
View File

@@ -0,0 +1,258 @@
describe('StackTrace', function() {
it('understands Chrome/IE/Edge style traces', function() {
var error = {
message: 'nope',
stack:
'Error: nope\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error: nope');
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw:
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it('understands Chrome/IE/Edge style traces with multiline messages', function() {
var error = {
message: 'line 1\nline 2',
stack:
'Error: line 1\nline 2\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error: line 1\nline 2');
var rawFrames = result.frames.map(function(f) {
return f.raw;
});
expect(rawFrames).toEqual([
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
]);
});
it('understands Node style traces', function() {
var error = {
message: 'nope',
stack:
'Error\n' +
' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9\n' +
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)\n' +
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
' at runCallback (timers.js:672:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('Error');
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw: ' at /somewhere/jasmine/lib/jasmine-core/jasmine.js:4255:9',
func: undefined,
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 4255
},
{
raw:
' at QueueRunner.complete [as onComplete] (/somewhere/jasmine/lib/jasmine-core/jasmine.js:579:9)',
func: 'QueueRunner.complete [as onComplete]',
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 579
},
{
raw:
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)',
func: 'Immediate.<anonymous>',
file: '/somewhere/jasmine/lib/jasmine-core/jasmine.js',
line: 4314
},
{
raw: ' at runCallback (timers.js:672:20)',
func: 'runCallback',
file: 'timers.js',
line: 672
}
]);
});
it('understands Safari/Firefox/Phantom-OS X style traces', function() {
var error = {
message: 'nope',
stack:
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toBeFalsy();
expect(result.style).toEqual('webkit');
expect(result.frames).toEqual([
{
raw: 'http://localhost:8888/__spec__/core/UtilSpec.js:115:28',
func: undefined,
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: 'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27',
func: 'run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it('does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces', function() {
var error = {
message: 'nope',
stack: 'randomcharsnotincludingwhitespace'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.style).toBeNull();
expect(result.frames).toEqual([{ raw: error.stack }]);
});
it('understands Phantom-Linux style traces', function() {
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toBeFalsy();
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw:
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it('ignores blank lines', function() {
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.frames).toEqual([
{
raw:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
}
]);
});
it("omits properties except 'raw' for frames that are not understood", function() {
var error = {
message: 'nope',
stack:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' but this is quite unexpected\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.style).toEqual('v8');
expect(result.frames).toEqual([
{
raw:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw: ' but this is quite unexpected'
},
{
raw:
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
});
it('consideres different types of errors', function() {
var error = {
message: 'nope',
stack:
'TypeError: nope\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result = new jasmineUnderTest.StackTrace(error);
expect(result.message).toEqual('TypeError: nope');
expect(result.frames).toEqual([
{
raw:
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)',
func: 'UserContext.<anonymous>',
file: 'http://localhost:8888/__spec__/core/UtilSpec.js',
line: 115
},
{
raw:
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)',
func: 'QueueRunner.run',
file: 'http://localhost:8888/__jasmine__/jasmine.js',
line: 4320
}
]);
var no_error = {
message: 'nope',
stack:
'Type Error: nope\n' +
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n' +
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
};
var result_no_error = new jasmineUnderTest.StackTrace(no_error);
expect(result_no_error.message).not.toEqual(jasmine.anything());
});
});

View File

@@ -1,47 +1,52 @@
describe("Suite", function() {
describe('Suite', function() {
var env;
it("keeps its id", function() {
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
env: env,
id: 456,
description: "I am a suite"
});
beforeEach(function() {
env = new jasmineUnderTest.Env();
});
afterEach(function() {
env.cleanup_();
});
it('keeps its id', function() {
var suite = new jasmineUnderTest.Suite({
env: env,
id: 456,
description: 'I am a suite'
});
expect(suite.id).toEqual(456);
});
it("returns blank full name for top level suite", function() {
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
env: env,
description: "I am a suite"
});
it('returns blank full name for top level suite', function() {
var suite = new jasmineUnderTest.Suite({
env: env,
description: 'I am a suite'
});
expect(suite.getFullName()).toEqual("");
expect(suite.getFullName()).toEqual('');
});
it("returns its full name when it has parent suites", function() {
var env = new jasmineUnderTest.Env(),
parentSuite = new jasmineUnderTest.Suite({
it('returns its full name when it has parent suites', function() {
var parentSuite = new jasmineUnderTest.Suite({
env: env,
description: "I am a parent suite",
description: 'I am a parent suite',
parentSuite: jasmine.createSpy('pretend top level suite')
}),
suite = new jasmineUnderTest.Suite({
env: env,
description: "I am a suite",
description: 'I am a suite',
parentSuite: parentSuite
});
expect(suite.getFullName()).toEqual("I am a parent suite I am a suite");
expect(suite.getFullName()).toEqual('I am a parent suite I am a suite');
});
it("adds before functions in order of needed execution", function() {
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
it('adds before functions in order of needed execution', function() {
var suite = new jasmineUnderTest.Suite({
env: env,
description: "I am a suite"
description: 'I am a suite'
}),
outerBefore = jasmine.createSpy('outerBeforeEach'),
innerBefore = jasmine.createSpy('insideBeforeEach');
@@ -52,11 +57,10 @@ describe("Suite", function() {
expect(suite.beforeFns).toEqual([innerBefore, outerBefore]);
});
it("adds after functions in order of needed execution", function() {
var env = new jasmineUnderTest.Env(),
suite = new jasmineUnderTest.Suite({
it('adds after functions in order of needed execution', function() {
var suite = new jasmineUnderTest.Suite({
env: env,
description: "I am a suite"
description: 'I am a suite'
}),
outerAfter = jasmine.createSpy('outerAfterEach'),
innerAfter = jasmine.createSpy('insideAfterEach');
@@ -67,64 +71,37 @@ describe("Suite", function() {
expect(suite.afterFns).toEqual([innerAfter, outerAfter]);
});
it('has a status of failed if any afterAll expectations have failed', function() {
it('has a status of failed if any expectations have failed', function() {
var suite = new jasmineUnderTest.Suite({
expectationResultFactory: function() { return 'hi'; }
expectationResultFactory: function() {
return 'hi';
}
});
suite.addChild({ result: { status: 'done' } });
suite.addExpectationResult(false);
expect(suite.status()).toBe('failed');
});
it("retrieves a result with updated status", function() {
it('retrieves a result with updated status', function() {
var suite = new jasmineUnderTest.Suite({});
expect(suite.getResult().status).toBe('finished');
expect(suite.getResult().status).toBe('passed');
});
it("retrieves a result with pending status", function() {
it('retrieves a result with pending status', function() {
var suite = new jasmineUnderTest.Suite({});
suite.pend();
expect(suite.getResult().status).toBe('pending');
});
it("is executable if not pending", function() {
var suite = new jasmineUnderTest.Suite({});
expect(suite.isExecutable()).toBe(true);
});
it("is not executable if pending", function() {
var suite = new jasmineUnderTest.Suite({});
suite.pend();
expect(suite.isExecutable()).toBe(false);
});
it("tells all children about expectation failures, even if one throws", function() {
var suite = new jasmineUnderTest.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() {
it('throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set', function() {
var suite = new jasmineUnderTest.Suite({
expectationResultFactory: function(data) { return data; },
expectationResultFactory: function(data) {
return data;
},
throwOnExpectationFailure: true
});
suite.addChild({ result: { status: 'done' } });
expect(function() {
suite.addExpectationResult(false, 'failed');
@@ -134,22 +111,117 @@ describe("Suite", function() {
expect(suite.result.failedExpectations).toEqual(['failed']);
});
it("does not add an additional failure when an expectation fails in an afterAll", function(){
it('does not add an additional failure when an expectation fails', function() {
var suite = new jasmineUnderTest.Suite({});
suite.addChild({ result: { status: 'done' } });
suite.onException(new jasmineUnderTest.errors.ExpectationFailed());
expect(suite.getResult().failedExpectations).toEqual([]);
});
it('calls timer to compute duration', function() {
var suite = new jasmineUnderTest.Suite({
env: env,
id: 456,
description: 'I am a suite',
timer: jasmine.createSpyObj('timer', { start: null, elapsed: 77000 })
});
suite.startTimer();
suite.endTimer();
expect(suite.getResult().duration).toEqual(77000);
});
describe('#sharedUserContext', function() {
beforeEach(function() {
this.suite = new jasmineUnderTest.Suite({});
});
it('returns a UserContext', function() {
expect(this.suite.sharedUserContext().constructor).toBe(jasmineUnderTest.UserContext);
expect(this.suite.sharedUserContext().constructor).toBe(
jasmineUnderTest.UserContext
);
});
});
describe('attr.autoCleanClosures', function() {
function arrangeSuite(attrs) {
var suite = new jasmineUnderTest.Suite(attrs);
suite.beforeAll(function() {});
suite.beforeEach(function() {});
suite.afterEach(function() {});
suite.afterAll(function() {});
return suite;
}
it('should clean closures when "attr.autoCleanClosures" is missing', function() {
var suite = arrangeSuite({});
suite.cleanupBeforeAfter();
expect(suite.beforeAllFns[0].fn).toBe(null);
expect(suite.beforeFns[0].fn).toBe(null);
expect(suite.afterFns[0].fn).toBe(null);
expect(suite.afterAllFns[0].fn).toBe(null);
});
it('should clean closures when "attr.autoCleanClosures" is true', function() {
var suite = arrangeSuite({ autoCleanClosures: true });
suite.cleanupBeforeAfter();
expect(suite.beforeAllFns[0].fn).toBe(null);
expect(suite.beforeFns[0].fn).toBe(null);
expect(suite.afterFns[0].fn).toBe(null);
expect(suite.afterAllFns[0].fn).toBe(null);
});
it('should NOT clean closures when "attr.autoCleanClosures" is false', function() {
var suite = arrangeSuite({ autoCleanClosures: false });
suite.cleanupBeforeAfter();
expect(suite.beforeAllFns[0].fn).not.toBe(null);
expect(suite.beforeFns[0].fn).not.toBe(null);
expect(suite.afterFns[0].fn).not.toBe(null);
expect(suite.afterAllFns[0].fn).not.toBe(null);
});
});
describe('#reset', function() {
it('should reset the "pending" status', function() {
var suite = new jasmineUnderTest.Suite({});
suite.pend();
suite.reset();
expect(suite.getResult().status).toBe('passed');
});
it('should not reset the "pending" status when the suite was excluded', function() {
var suite = new jasmineUnderTest.Suite({});
suite.exclude();
suite.reset();
expect(suite.getResult().status).toBe('pending');
});
it('should also reset the children', function() {
var suite = new jasmineUnderTest.Suite({});
var child1 = jasmine.createSpyObj(['reset']);
var child2 = jasmine.createSpyObj(['reset']);
suite.addChild(child1);
suite.addChild(child2);
suite.reset();
expect(child1.reset).toHaveBeenCalled();
expect(child2.reset).toHaveBeenCalled();
});
it('should reset the failedExpectations', function() {
var suite = new jasmineUnderTest.Suite({
expectationResultFactory: function(error) {
return error;
}
});
suite.onException(new Error());
suite.reset();
var result = suite.getResult();
expect(result.status).toBe('passed');
expect(result.failedExpectations).toHaveSize(0);
});
});
});

View File

@@ -1,7 +1,7 @@
describe("Timer", function() {
it("reports the time elapsed", function() {
describe('Timer', function() {
it('reports the time elapsed', function() {
var fakeNow = jasmine.createSpy('fake Date.now'),
timer = new jasmineUnderTest.Timer({now: fakeNow});
timer = new jasmineUnderTest.Timer({ now: fakeNow });
fakeNow.and.returnValue(100);
timer.start();
@@ -11,7 +11,7 @@ describe("Timer", function() {
expect(timer.elapsed()).toEqual(100);
});
describe("when date is stubbed, perhaps by other testing helpers", function() {
describe('when date is stubbed, perhaps by other testing helpers', function() {
var origDate = Date;
beforeEach(function() {
Date = jasmine.createSpy('date spy');
@@ -21,7 +21,7 @@ describe("Timer", function() {
Date = origDate;
});
it("does not throw even though Date was taken away", function() {
it('does not throw even though Date was taken away', function() {
var timer = new jasmineUnderTest.Timer();
expect(timer.start).not.toThrow();

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
describe("UserContext", function() {
it("Behaves just like an plain object", function() {
describe('UserContext', function() {
it('Behaves just like an plain object', function() {
var context = new jasmineUnderTest.UserContext(),
properties = [];
properties = [];
for (var prop in context) {
if (obj.hasOwnProperty(prop)) {
@@ -32,7 +32,7 @@ describe("UserContext", function() {
describe('when using a regular object as parameter', function() {
beforeEach(function() {
this.context = {};
this.value = 'value'
this.value = 'value';
this.context.key = this.value;
this.cloned = jasmineUnderTest.UserContext.fromExisting(this.context);
});
@@ -51,4 +51,3 @@ describe("UserContext", function() {
});
});
});

View File

@@ -1,11 +1,11 @@
describe("jasmineUnderTest.util", function() {
describe("isArray_", function() {
it("should return true if the argument is an array", function() {
describe('jasmineUnderTest.util', function() {
describe('isArray_', function() {
it('should return true if the argument is an array', function() {
expect(jasmineUnderTest.isArray_([])).toBe(true);
expect(jasmineUnderTest.isArray_(['a'])).toBe(true);
});
it("should return false if the argument is not an array", function() {
it('should return false if the argument is not an array', function() {
expect(jasmineUnderTest.isArray_(undefined)).toBe(false);
expect(jasmineUnderTest.isArray_({})).toBe(false);
expect(jasmineUnderTest.isArray_(function() {})).toBe(false);
@@ -15,13 +15,13 @@ describe("jasmineUnderTest.util", function() {
});
});
describe("isObject_", function() {
it("should return true if the argument is an object", function() {
describe('isObject_', function() {
it('should return true if the argument is an object', function() {
expect(jasmineUnderTest.isObject_({})).toBe(true);
expect(jasmineUnderTest.isObject_({an: "object"})).toBe(true);
expect(jasmineUnderTest.isObject_({ an: 'object' })).toBe(true);
});
it("should return false if the argument is not an object", function() {
it('should return false if the argument is not an object', function() {
expect(jasmineUnderTest.isObject_(undefined)).toBe(false);
expect(jasmineUnderTest.isObject_([])).toBe(false);
expect(jasmineUnderTest.isObject_(function() {})).toBe(false);
@@ -31,32 +31,126 @@ describe("jasmineUnderTest.util", function() {
});
});
describe("isUndefined", function() {
it("reports if a variable is defined", function() {
describe('promise utils', function() {
var mockNativePromise, mockPromiseLikeObject;
var mockPromiseLike = function() {
this.then = function() {};
};
beforeEach(function() {
jasmine.getEnv().requirePromises();
mockNativePromise = new Promise(function(res, rej) {}); // eslint-disable-line compat/compat
mockPromiseLikeObject = new mockPromiseLike();
});
describe('isPromise', function() {
it('should return true when passed a native promise', function() {
expect(jasmineUnderTest.isPromise(mockNativePromise)).toBe(true);
});
it('should return false for promise like objects', function() {
expect(jasmineUnderTest.isPromise(mockPromiseLikeObject)).toBe(false);
});
it('should return false for strings', function() {
expect(jasmineUnderTest.isPromise('hello')).toBe(false);
});
it('should return false for numbers', function() {
expect(jasmineUnderTest.isPromise(3)).toBe(false);
});
it('should return false for null', function() {
expect(jasmineUnderTest.isPromise(null)).toBe(false);
});
it('should return false for undefined', function() {
expect(jasmineUnderTest.isPromise(undefined)).toBe(false);
});
it('should return false for arrays', function() {
expect(jasmineUnderTest.isPromise([])).toBe(false);
});
it('should return false for objects', function() {
expect(jasmineUnderTest.isPromise({})).toBe(false);
});
it('should return false for boolean values', function() {
expect(jasmineUnderTest.isPromise(true)).toBe(false);
});
});
describe('isPromiseLike', function() {
it('should return true when passed a native promise', function() {
expect(jasmineUnderTest.isPromiseLike(mockNativePromise)).toBe(true);
});
it('should return true for promise like objects', function() {
expect(jasmineUnderTest.isPromiseLike(mockPromiseLikeObject)).toBe(
true
);
});
it('should return false if then is not a function', function() {
expect(
jasmineUnderTest.isPromiseLike({ then: { its: 'Not a function :O' } })
).toBe(false);
});
it('should return false for strings', function() {
expect(jasmineUnderTest.isPromiseLike('hello')).toBe(false);
});
it('should return false for numbers', function() {
expect(jasmineUnderTest.isPromiseLike(3)).toBe(false);
});
it('should return false for null', function() {
expect(jasmineUnderTest.isPromiseLike(null)).toBe(false);
});
it('should return false for undefined', function() {
expect(jasmineUnderTest.isPromiseLike(undefined)).toBe(false);
});
it('should return false for arrays', function() {
expect(jasmineUnderTest.isPromiseLike([])).toBe(false);
});
it('should return false for objects', function() {
expect(jasmineUnderTest.isPromiseLike({})).toBe(false);
});
it('should return false for boolean values', function() {
expect(jasmineUnderTest.isPromiseLike(true)).toBe(false);
});
});
});
describe('isUndefined', function() {
it('reports if a variable is defined', function() {
var a;
expect(jasmineUnderTest.util.isUndefined(a)).toBe(true);
expect(jasmineUnderTest.util.isUndefined(undefined)).toBe(true);
var undefined = "diz be undefined yo";
var undefined = 'diz be undefined yo';
expect(jasmineUnderTest.util.isUndefined(undefined)).toBe(false);
});
});
describe("getPropertyDescriptor", function() {
// IE 8 doesn't support `definePropery` on non-DOM nodes
if (jasmine.getEnv().ieVersion < 9) { return; }
it("get property descriptor from object", function() {
var obj = {prop: 1},
describe('getPropertyDescriptor', function() {
it('get property descriptor from object', function() {
var obj = { prop: 1 },
actual = jasmineUnderTest.util.getPropertyDescriptor(obj, 'prop'),
expected = Object.getOwnPropertyDescriptor(obj, 'prop');
expect(actual).toEqual(expected);
});
it("get property descriptor from object property", function() {
var proto = {prop: 1},
obj = Object.create(proto),
it('get property descriptor from object property', function() {
var proto = { prop: 1 },
actual = jasmineUnderTest.util.getPropertyDescriptor(proto, 'prop'),
expected = Object.getOwnPropertyDescriptor(proto, 'prop');
@@ -64,8 +158,8 @@ describe("jasmineUnderTest.util", function() {
});
});
describe("objectDifference", function() {
it("given two objects A and B, returns the properties in A not present in B", function() {
describe('objectDifference', function() {
it('given two objects A and B, returns the properties in A not present in B', function() {
var a = {
foo: 3,
bar: 4,
@@ -77,10 +171,13 @@ describe("jasmineUnderTest.util", function() {
quux: 7
};
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({foo: 3, baz: 5})
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({
foo: 3,
baz: 5
});
});
it("only looks at own properties of both objects", function() {
it('only looks at own properties of both objects', function() {
function Foo() {}
Foo.prototype.x = 1;
@@ -92,8 +189,17 @@ describe("jasmineUnderTest.util", function() {
var b = new Foo();
b.y = 2;
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({x: 1});
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({y: 2});
})
})
expect(jasmineUnderTest.util.objectDifference(a, b)).toEqual({ x: 1 });
expect(jasmineUnderTest.util.objectDifference(b, a)).toEqual({ y: 2 });
});
});
describe('jasmineFile', function() {
it('returns the file containing jasmine.util', function() {
// Chrome sometimes reports foo.js as foo.js/, so tolerate
// a trailing slash if present.
expect(jasmineUnderTest.util.jasmineFile()).toMatch(/util.js\/?$/);
expect(jasmine.util.jasmineFile()).toMatch(/jasmine.js\/?$/);
});
});
});

View File

@@ -0,0 +1,139 @@
describe('asymmetricEqualityTesterArgCompatShim', function() {
it('provides all the properties of the MatchersUtil', function() {
var matchersUtil = {
foo: function() {},
bar: function() {}
},
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(
matchersUtil,
[]
);
expect(shim.foo).toBe(matchersUtil.foo);
expect(shim.bar).toBe(matchersUtil.bar);
});
it('provides all the properties of the customEqualityTesters', function() {
var customEqualityTesters = [function() {}, function() {}],
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(
{},
customEqualityTesters
);
expect(shim.length).toBe(2);
expect(shim[0]).toBe(customEqualityTesters[0]);
expect(shim[1]).toBe(customEqualityTesters[1]);
});
it('provides all the properties of Array.prototype', function() {
var shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []);
expect(shim.filter).toBe(Array.prototype.filter);
expect(shim.forEach).toBe(Array.prototype.forEach);
expect(shim.map).toBe(Array.prototype.map);
});
it('provides properties of Array.prototype', function() {
var keys = [
'concat',
'every',
'filter',
'forEach',
'indexOf',
'join',
'lastIndexOf',
'length',
'map',
'pop',
'push',
'reduce',
'reduceRight',
'reverse',
'shift',
'slice',
'some',
'sort',
'splice',
'unshift'
],
optionalKeys = [
'copyWithin',
'entries',
'fill',
'find',
'findIndex',
'flat',
'flatMap',
'includes',
'keys',
'values'
],
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim({}, []),
i,
k;
// Properties that are present on all supported runtimes
for (i = 0; i < keys.length; i++) {
k = keys[i];
expect(shim[k])
.withContext(k)
.not.toBeUndefined();
expect(shim[k])
.withContext(k)
.toBe(Array.prototype[k]);
}
// Properties that are present on only some supported runtimes
for (i = 0; i < optionalKeys.length; i++) {
k = optionalKeys[i];
if (shim[k] !== undefined) {
expect(shim[k])
.withContext(k)
.toBe(Array.prototype[k]);
}
}
});
describe('When Array.prototype additions collide with MatchersUtil methods', function() {
function keys() {
return [
'contains',
'buildFailureMessage',
'asymmetricDiff_',
'asymmetricMatch_',
'equals',
'eq_'
];
}
beforeEach(function() {
keys().forEach(function(k) {
expect(Array.prototype[k])
.withContext('Array.prototype already had ' + k)
.toBeUndefined();
Array.prototype[k] = function() {};
});
});
afterEach(function() {
keys().forEach(function(k) {
delete Array.prototype[k];
});
});
it('uses the MatchersUtil methods', function() {
var matchersUtil = new jasmineUnderTest.MatchersUtil({}),
shim = jasmineUnderTest.asymmetricEqualityTesterArgCompatShim(
matchersUtil,
[]
);
keys().forEach(function(k) {
expect(shim[k])
.withContext(k + ' was overwritten')
.toBe(jasmineUnderTest.MatchersUtil.prototype[k]);
});
});
});
});

View File

@@ -1,81 +1,86 @@
describe("Any", function() {
it("matches a string", function() {
describe('Any', function() {
it('matches a string', function() {
var any = new jasmineUnderTest.Any(String);
expect(any.asymmetricMatch("foo")).toBe(true);
expect(any.asymmetricMatch('foo')).toBe(true);
});
it("matches a number", function() {
it('matches a number', function() {
var any = new jasmineUnderTest.Any(Number);
expect(any.asymmetricMatch(1)).toBe(true);
});
it("matches a function", function() {
it('matches a function', function() {
var any = new jasmineUnderTest.Any(Function);
expect(any.asymmetricMatch(function(){})).toBe(true);
expect(any.asymmetricMatch(function() {})).toBe(true);
});
it("matches an Object", function() {
it('matches an Object', function() {
var any = new jasmineUnderTest.Any(Object);
expect(any.asymmetricMatch({})).toBe(true);
});
it("matches a Boolean", function() {
it('matches a Boolean', function() {
var any = new jasmineUnderTest.Any(Boolean);
expect(any.asymmetricMatch(true)).toBe(true);
});
it("matches a Map", function() {
it('matches a Map', function() {
jasmine.getEnv().requireFunctioningMaps();
var any = new jasmineUnderTest.Any(Map);
expect(any.asymmetricMatch(new Map())).toBe(true);
expect(any.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat
});
it("matches a Set", function() {
it('matches a Set', function() {
jasmine.getEnv().requireFunctioningSets();
var any = new jasmineUnderTest.Any(Set);
expect(any.asymmetricMatch(new Set())).toBe(true);
expect(any.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat
});
it("matches a TypedArray", function() {
jasmine.getEnv().requireFunctioningTypedArrays();
it('matches a TypedArray', function() {
var any = new jasmineUnderTest.Any(Uint32Array);
expect(any.asymmetricMatch(new Uint32Array([]))).toBe(true);
expect(any.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat
});
it("matches a Symbol", function() {
it('matches a Symbol', function() {
jasmine.getEnv().requireFunctioningSymbols();
var any = new jasmineUnderTest.Any(Symbol);
var any = new jasmineUnderTest.Any(Symbol); // eslint-disable-line compat/compat
expect(any.asymmetricMatch(Symbol())).toBe(true);
expect(any.asymmetricMatch(Symbol())).toBe(true); // eslint-disable-line compat/compat
});
it("matches another constructed object", function() {
it('matches another constructed object', function() {
var Thing = function() {},
any = new jasmineUnderTest.Any(Thing);
expect(any.asymmetricMatch(new Thing())).toBe(true);
});
it('does not treat null as an Object', function() {
var any = new jasmineUnderTest.Any(Object);
expect(any.asymmetricMatch(null)).toBe(false);
});
it("jasmineToString's itself", function() {
var any = new jasmineUnderTest.Any(Number);
expect(any.jasmineToString()).toEqual('<jasmine.any(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() {
describe('when called without an argument', function() {
it('tells the user to pass a constructor or use jasmine.anything()', function() {
expect(function() {
new jasmineUnderTest.Any();
}).toThrowError(TypeError, /constructor.*anything/);

View File

@@ -1,58 +1,56 @@
describe("Anything", function() {
it("matches a string", function() {
describe('Anything', function() {
it('matches a string', function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch('foo')).toBe(true);
});
it("matches a number", function() {
it('matches a number', function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch(42)).toBe(true);
});
it("matches an object", function() {
it('matches an object', function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch({ foo: 'bar' })).toBe(true);
});
it("matches an array", function() {
it('matches an array', function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch([1,2,3])).toBe(true);
expect(anything.asymmetricMatch([1, 2, 3])).toBe(true);
});
it("matches a Map", function() {
it('matches a Map', function() {
jasmine.getEnv().requireFunctioningMaps();
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch(new Map())).toBe(true);
expect(anything.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat
});
it("matches a Set", function() {
it('matches a Set', function() {
jasmine.getEnv().requireFunctioningSets();
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch(new Set())).toBe(true);
expect(anything.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat
});
it("matches a TypedArray", function() {
jasmine.getEnv().requireFunctioningTypedArrays();
it('matches a TypedArray', function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch(new Uint32Array([]))).toBe(true);
expect(anything.asymmetricMatch(new Uint32Array([]))).toBe(true); // eslint-disable-line compat/compat
});
it("matches a Symbol", function() {
it('matches a Symbol', function() {
jasmine.getEnv().requireFunctioningSymbols();
var anything = new jasmineUnderTest.Anything();
expect(anything.asymmetricMatch(Symbol())).toBe(true);
expect(anything.asymmetricMatch(Symbol())).toBe(true); // eslint-disable-line compat/compat
});
it("doesn't match undefined", function() {
@@ -71,6 +69,6 @@ describe("Anything", function() {
it("jasmineToString's itself", function() {
var anything = new jasmineUnderTest.Anything();
expect(anything.jasmineToString()).toEqual("<jasmine.anything>");
expect(anything.jasmineToString()).toEqual('<jasmine.anything>');
});
});

View File

@@ -1,52 +1,74 @@
describe("ArrayContaining", function() {
it("matches any actual to an empty array", function() {
describe('ArrayContaining', function() {
it('matches any actual to an empty array', function() {
var containing = new jasmineUnderTest.ArrayContaining([]);
expect(containing.asymmetricMatch("foo")).toBe(true);
expect(containing.asymmetricMatch('foo')).toBe(true);
});
it("does not work when not passed an array", function() {
var containing = new jasmineUnderTest.ArrayContaining("foo");
it('does not work when not passed an array', function() {
var containing = new jasmineUnderTest.ArrayContaining('foo');
expect(function() {
containing.asymmetricMatch([]);
}).toThrowError(/not 'foo'/);
});
it("matches when the item is in the actual", function() {
var containing = new jasmineUnderTest.ArrayContaining(["foo"]);
it('matches when the item is in the actual', function() {
var containing = new jasmineUnderTest.ArrayContaining(['foo']);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(["foo"])).toBe(true);
expect(containing.asymmetricMatch(['foo'], matchersUtil)).toBe(true);
});
it("matches when additional items are in the actual", function() {
var containing = new jasmineUnderTest.ArrayContaining(["foo"]);
it('matches when additional items are in the actual', function() {
var containing = new jasmineUnderTest.ArrayContaining(['foo']);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(["foo", "bar"])).toBe(true);
expect(containing.asymmetricMatch(['foo', 'bar'], matchersUtil)).toBe(true);
});
it("does not match when the item is not in the actual", function() {
var containing = new jasmineUnderTest.ArrayContaining(["foo"]);
it('does not match when the item is not in the actual', function() {
var containing = new jasmineUnderTest.ArrayContaining(['foo']);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(["bar"])).toBe(false);
expect(containing.asymmetricMatch(['bar'], matchersUtil)).toBe(false);
});
it("jasmineToStrings itself", function() {
var containing = new jasmineUnderTest.ArrayContaining([]);
it('does not match when the actual is not an array', function() {
var containing = new jasmineUnderTest.ArrayContaining(['foo']);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.jasmineToString()).toMatch("<jasmine.arrayContaining");
expect(containing.asymmetricMatch('foo', matchersUtil)).toBe(false);
});
it("uses custom equality testers", function() {
it('jasmineToStrings itself', function() {
var sample = [],
matcher = new jasmineUnderTest.ArrayContaining(sample),
pp = jasmine.createSpy('pp').and.returnValue('sample');
expect(matcher.jasmineToString(pp)).toEqual(
'<jasmine.arrayContaining(sample)>'
);
expect(pp).toHaveBeenCalledWith(sample);
});
it('uses custom equality testers', function() {
var tester = function(a, b) {
// All "foo*" strings match each other.
if (typeof a == "string" && typeof b == "string" &&
a.substr(0, 3) == "foo" && b.substr(0, 3) == "foo") {
if (
typeof a == 'string' &&
typeof b == 'string' &&
a.substr(0, 3) == 'foo' &&
b.substr(0, 3) == 'foo'
) {
return true;
}
};
var containing = new jasmineUnderTest.ArrayContaining(["fooVal"]);
var containing = new jasmineUnderTest.ArrayContaining(['fooVal']);
var matchersUtil = new jasmineUnderTest.MatchersUtil({
customTesters: [tester]
});
expect(containing.asymmetricMatch(["fooBar"], [tester])).toBe(true);
expect(containing.asymmetricMatch(['fooBar'], matchersUtil)).toBe(true);
});
});

View File

@@ -1,47 +1,64 @@
describe("ArrayWithExactContents", function() {
it("matches an array with the same items in a different order", function() {
describe('ArrayWithExactContents', function() {
it('matches an array with the same items in a different order', function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a', 2, /a/]);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(matcher.asymmetricMatch([2, 'a', /a/])).toBe(true);
expect(matcher.asymmetricMatch([2, 'a', /a/], matchersUtil)).toBe(true);
});
it("does not work when not passed an array", function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents("foo");
it('does not work when not passed an array', function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents('foo');
expect(function() {
matcher.asymmetricMatch([]);
}).toThrowError(/not 'foo'/);
});
it("does not match when an item is missing", function() {
it('does not match when an item is missing', function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a', 2, /a/]);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(matcher.asymmetricMatch(['a', 2])).toBe(false);
expect(matcher.asymmetricMatch(['a', 2, undefined])).toBe(false);
expect(matcher.asymmetricMatch(['a', 2], matchersUtil)).toBe(false);
expect(matcher.asymmetricMatch(['a', 2, undefined], matchersUtil)).toBe(
false
);
});
it("does not match when there is an extra item", function() {
it('does not match when there is an extra item', function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents(['a']);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(matcher.asymmetricMatch(['a', 2])).toBe(false);
expect(matcher.asymmetricMatch(['a', 2], matchersUtil)).toBe(false);
});
it("jasmineToStrings itself", function() {
var matcher = new jasmineUnderTest.ArrayWithExactContents([]);
it('jasmineToStrings itself', function() {
var sample = [],
matcher = new jasmineUnderTest.ArrayWithExactContents(sample),
pp = jasmine.createSpy('pp').and.returnValue('sample');
expect(matcher.jasmineToString()).toMatch("<jasmine.arrayWithExactContents");
expect(matcher.jasmineToString(pp)).toEqual(
'<jasmine.arrayWithExactContents(sample)>'
);
expect(pp).toHaveBeenCalledWith(sample);
});
it("uses custom equality testers", function() {
it('uses custom equality testers', function() {
var tester = function(a, b) {
// All "foo*" strings match each other.
if (typeof a == "string" && typeof b == "string" &&
a.substr(0, 3) == "foo" && b.substr(0, 3) == "foo") {
if (
typeof a == 'string' &&
typeof b == 'string' &&
a.substr(0, 3) == 'foo' &&
b.substr(0, 3) == 'foo'
) {
return true;
}
};
var matcher = new jasmineUnderTest.ArrayWithExactContents(["fooVal"]);
var matcher = new jasmineUnderTest.ArrayWithExactContents(['fooVal']);
var matchersUtil = new jasmineUnderTest.MatchersUtil({
customTesters: [tester]
});
expect(matcher.asymmetricMatch(["fooBar"], [tester])).toBe(true);
expect(matcher.asymmetricMatch(['fooBar'], matchersUtil)).toBe(true);
});
});

View File

@@ -0,0 +1,50 @@
describe('Empty', function() {
it('matches an empty object', function() {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch({})).toBe(true);
expect(empty.asymmetricMatch({ undefined: false })).toBe(false);
});
it('matches an empty array', function() {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch([])).toBe(true);
expect(empty.asymmetricMatch([1, 12, 3])).toBe(false);
});
it('matches an empty string', function() {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch('')).toBe(true);
expect(empty.asymmetricMatch('')).toBe(true);
expect(empty.asymmetricMatch('12312')).toBe(false);
});
it('matches an empty map', function() {
jasmine.getEnv().requireFunctioningMaps();
var empty = new jasmineUnderTest.Empty();
var fullMap = new Map(); // eslint-disable-line compat/compat
fullMap.set('thing', 2);
expect(empty.asymmetricMatch(new Map())).toBe(true); // eslint-disable-line compat/compat
expect(empty.asymmetricMatch(fullMap)).toBe(false);
});
it('matches an empty set', function() {
jasmine.getEnv().requireFunctioningSets();
var empty = new jasmineUnderTest.Empty();
var fullSet = new Set(); // eslint-disable-line compat/compat
fullSet.add(3);
expect(empty.asymmetricMatch(new Set())).toBe(true); // eslint-disable-line compat/compat
expect(empty.asymmetricMatch(fullSet)).toBe(false);
});
it('matches an empty typed array', function() {
var empty = new jasmineUnderTest.Empty();
expect(empty.asymmetricMatch(new Int16Array())).toBe(true); // eslint-disable-line compat/compat
expect(empty.asymmetricMatch(new Int16Array([1, 2]))).toBe(false); // eslint-disable-line compat/compat
});
});

View File

@@ -0,0 +1,38 @@
describe('Falsy', function() {
it('is true for an empty string', function() {
var falsy = new jasmineUnderTest.Falsy();
expect(falsy.asymmetricMatch('')).toBe(true);
expect(falsy.asymmetricMatch('')).toBe(true);
expect(falsy.asymmetricMatch('asdasdad')).toBe(false);
});
it('is false for a number that is 0', function() {
var falsy = new jasmineUnderTest.Falsy(Number);
expect(falsy.asymmetricMatch(1)).toBe(false);
expect(falsy.asymmetricMatch(0)).toBe(true);
expect(falsy.asymmetricMatch(-23)).toBe(false);
expect(falsy.asymmetricMatch(-3.1)).toBe(false);
});
it('is true for a null or undefined', function() {
var falsy = new jasmineUnderTest.Falsy(Function);
expect(falsy.asymmetricMatch(null)).toBe(true);
expect(falsy.asymmetricMatch(undefined)).toBe(true);
});
it('is true for NaN', function() {
var falsy = new jasmineUnderTest.Falsy(Object);
expect(falsy.asymmetricMatch(NaN)).toBe(true);
});
it('is true for a false Boolean', function() {
var falsy = new jasmineUnderTest.Falsy(Boolean);
expect(falsy.asymmetricMatch(false)).toBe(true);
expect(falsy.asymmetricMatch(true)).toBe(false);
});
});

View File

@@ -0,0 +1,171 @@
/* eslint-disable compat/compat */
describe('MapContaining', function() {
function MapI(iterable) {
// for IE11
var map = new Map();
iterable.forEach(function(kv) {
map.set(kv[0], kv[1]);
});
return map;
}
beforeEach(function() {
jasmine.getEnv().requireFunctioningMaps();
});
it('matches any actual map to an empty map', function() {
var actualMap = new MapI([['foo', 'bar']]);
var containing = new jasmineUnderTest.MapContaining(new Map());
expect(containing.asymmetricMatch(actualMap)).toBe(true);
});
it('matches when all the key/value pairs in sample have matches in actual', function() {
var actualMap = new MapI([
['foo', [1, 2, 3]],
[{ foo: 'bar' }, 'baz'],
['other', 'any']
]);
var containingMap = new MapI([[{ foo: 'bar' }, 'baz'], ['foo', [1, 2, 3]]]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(true);
});
it('does not match when a key is not in actual', function() {
var actualMap = new MapI([
['foo', [1, 2, 3]],
[{ foo: 'not a bar' }, 'baz']
]);
var containingMap = new MapI([[{ foo: 'bar' }, 'baz'], ['foo', [1, 2, 3]]]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(false);
});
it('does not match when a value is not in actual', function() {
var actualMap = new MapI([['foo', [1, 2, 3]], [{ foo: 'bar' }, 'baz']]);
var containingMap = new MapI([[{ foo: 'bar' }, 'baz'], ['foo', [1, 2]]]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(false);
});
it('matches when all the key/value pairs in sample have asymmetric matches in actual', function() {
var actualMap = new MapI([
['foo1', 'not a bar'],
['foo2', 'bar'],
['baz', [1, 2, 3, 4]]
]);
var containingMap = new MapI([
[jasmineUnderTest.stringMatching(/^foo\d/), 'bar'],
['baz', jasmineUnderTest.arrayContaining([2, 3])]
]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(true);
});
it('does not match when a key in sample has no asymmetric matches in actual', function() {
var actualMap = new MapI([['a-foo1', 'bar'], ['baz', [1, 2, 3, 4]]]);
var containingMap = new MapI([
[jasmineUnderTest.stringMatching(/^foo\d/), 'bar'],
['baz', jasmineUnderTest.arrayContaining([2, 3])]
]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(false);
});
it('does not match when a value in sample has no asymmetric matches in actual', function() {
var actualMap = new MapI([['foo1', 'bar'], ['baz', [1, 2, 3, 4]]]);
var containingMap = new MapI([
[jasmineUnderTest.stringMatching(/^foo\d/), 'bar'],
['baz', jasmineUnderTest.arrayContaining([4, 5])]
]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(false);
});
it('matches recursively', function() {
var actualMap = new MapI([
['foo', new MapI([['foo1', 1], ['foo2', 2]])],
[new MapI([[1, 'bar1'], [2, 'bar2']]), 'bar'],
['other', 'any']
]);
var containingMap = new MapI([
['foo', new jasmineUnderTest.MapContaining(new MapI([['foo1', 1]]))],
[new jasmineUnderTest.MapContaining(new MapI([[2, 'bar2']])), 'bar']
]);
var containing = new jasmineUnderTest.MapContaining(containingMap);
var matchersUtil = new jasmineUnderTest.MatchersUtil();
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(true);
});
it('uses custom equality testers', function() {
function tester(a, b) {
// treat all negative numbers as equal
return typeof a == 'number' && typeof b == 'number'
? a < 0 && b < 0
: a === b;
}
var actualMap = new MapI([['foo', -1]]);
var containing = new jasmineUnderTest.MapContaining(
new MapI([['foo', -2]])
);
var matchersUtil = new jasmineUnderTest.MatchersUtil({
customTesters: [tester]
});
expect(containing.asymmetricMatch(actualMap, matchersUtil)).toBe(true);
});
it('does not match when actual is not a map', function() {
var containingMap = new MapI([['foo', 'bar']]);
expect(
new jasmineUnderTest.MapContaining(containingMap).asymmetricMatch('foo')
).toBe(false);
expect(
new jasmineUnderTest.MapContaining(containingMap).asymmetricMatch(-1)
).toBe(false);
expect(
new jasmineUnderTest.MapContaining(containingMap).asymmetricMatch({
foo: 'bar'
})
).toBe(false);
});
it('throws an error when sample is not a map', function() {
expect(function() {
new jasmineUnderTest.MapContaining({ foo: 'bar' }).asymmetricMatch(
new Map()
);
}).toThrowError(/You must provide a map/);
});
it('defines a `jasmineToString` method', function() {
var sample = new Map(),
containing = new jasmineUnderTest.MapContaining(sample),
pp = jasmine.createSpy('pp').and.returnValue('sample');
expect(containing.jasmineToString(pp)).toEqual(
'<jasmine.mapContaining(sample)>'
);
expect(pp).toHaveBeenCalledWith(sample);
});
});

Some files were not shown because too many files have changed in this diff Show More