Compare commits
395 Commits
v4.1.1
...
v6.0.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbcc1c924a | ||
|
|
90ee9a0cac | ||
|
|
b9f04f8702 | ||
|
|
e11f320df3 | ||
|
|
c2ce55580c | ||
|
|
4598e4049c | ||
|
|
168ff0a751 | ||
|
|
fbec066837 | ||
|
|
0688db88e9 | ||
|
|
190a13ed96 | ||
|
|
979e4a5d0f | ||
|
|
8863643d55 | ||
|
|
7214ccd3dc | ||
|
|
970cbdc69c | ||
|
|
4020da25a4 | ||
|
|
4a36ece65b | ||
|
|
17c0567bae | ||
|
|
e2a7740322 | ||
|
|
6e0342fc8e | ||
|
|
d333ecb5b1 | ||
|
|
1e98a4b61b | ||
|
|
7aaa16f576 | ||
|
|
ee696cbbf6 | ||
|
|
88289f592e | ||
|
|
0462500c31 | ||
|
|
72ecc70c5d | ||
|
|
f86f8c3331 | ||
|
|
70fbdc98b5 | ||
|
|
4166ea791c | ||
|
|
5439c8c9cd | ||
|
|
2c6ce35ccc | ||
|
|
7c34b43607 | ||
|
|
3040abe23d | ||
|
|
4d3f6b272a | ||
|
|
6ab83e25d1 | ||
|
|
27297de3b8 | ||
|
|
3cbf4dc27b | ||
|
|
6d77f3e7f0 | ||
|
|
124effe04b | ||
|
|
418e9a7728 | ||
|
|
6715f24fd0 | ||
|
|
fa481b2bd1 | ||
|
|
8309416cb2 | ||
|
|
4ccc7bf3ac | ||
|
|
cca6b2aa07 | ||
|
|
78940aa0fb | ||
|
|
3d8396da0a | ||
|
|
0bf9aff195 | ||
|
|
55b2e8846f | ||
|
|
3493519c9f | ||
|
|
62b5698a99 | ||
|
|
98849882a2 | ||
|
|
6665c4e123 | ||
|
|
3698f6fb5d | ||
|
|
60f34ec087 | ||
|
|
91bd3f8201 | ||
|
|
ca4fbcbccb | ||
|
|
e1532be726 | ||
|
|
54465f6f6a | ||
|
|
fa9939ae94 | ||
|
|
7978ad9889 | ||
|
|
af4662ad31 | ||
|
|
15c38c7728 | ||
|
|
b597975c7e | ||
|
|
09ce3a30b6 | ||
|
|
3bcbc2e3af | ||
|
|
fbaba902dc | ||
|
|
bf2e8e759e | ||
|
|
50e566bd67 | ||
|
|
4b7d5e3623 | ||
|
|
6449832e7e | ||
|
|
c6266b24b7 | ||
|
|
f16b81d4ef | ||
|
|
7feec406d9 | ||
|
|
f822ffea21 | ||
|
|
db65c3b131 | ||
|
|
fd37a7eac0 | ||
|
|
12219e80c1 | ||
|
|
a980ae6bf2 | ||
|
|
56ac8f5505 | ||
|
|
3780fe0b35 | ||
|
|
164a393932 | ||
|
|
759a867094 | ||
|
|
f94d0ceda9 | ||
|
|
8d99f27be8 | ||
|
|
63774597f0 | ||
|
|
a3e1abfa12 | ||
|
|
b89a870a59 | ||
|
|
ea3fc88803 | ||
|
|
d5884e33c6 | ||
|
|
138bf9be4b | ||
|
|
98d5284c19 | ||
|
|
2299c85751 | ||
|
|
8e3ec25f6d | ||
|
|
b009cd2922 | ||
|
|
8eee6ebb91 | ||
|
|
c15a1aaa6d | ||
|
|
5b06531cac | ||
|
|
42cca93926 | ||
|
|
395ef85954 | ||
|
|
5e88fde655 | ||
|
|
bb777e93e5 | ||
|
|
9d3fb167a2 | ||
|
|
3176eaf1d8 | ||
|
|
d31a431d1f | ||
|
|
84f78c1435 | ||
|
|
ff476b1982 | ||
|
|
d53d2ff3eb | ||
|
|
adfbd00c75 | ||
|
|
495e5fcd50 | ||
|
|
bc2aa7be25 | ||
|
|
af04599bb5 | ||
|
|
21db6ec0e3 | ||
|
|
2d07b3e6d7 | ||
|
|
6891789ed2 | ||
|
|
7a3d3c9360 | ||
|
|
1b2922e008 | ||
|
|
bd8d23f2a7 | ||
|
|
de26763868 | ||
|
|
f4be08b657 | ||
|
|
50ef882a1a | ||
|
|
c1cd5c6291 | ||
|
|
63ed2b3948 | ||
|
|
0183acc682 | ||
|
|
e15819c0dd | ||
|
|
f694194b2b | ||
|
|
94c00886a6 | ||
|
|
f5915d7963 | ||
|
|
15587f3ce3 | ||
|
|
3ecddc2555 | ||
|
|
6a7c0e6368 | ||
|
|
84daa0f5dc | ||
|
|
c6b3e947e9 | ||
|
|
0e604de0db | ||
|
|
e7ca9c5765 | ||
|
|
cbff6f95cb | ||
|
|
361640f52e | ||
|
|
e5d46e8624 | ||
|
|
8f6b3c49cc | ||
|
|
df6ab05280 | ||
|
|
9ea027dbff | ||
|
|
7cc7da4abc | ||
|
|
8be98e73ca | ||
|
|
52aaf63d22 | ||
|
|
a09fdd3284 | ||
|
|
89f3e9449d | ||
|
|
ba033c520d | ||
|
|
fc935e89c6 | ||
|
|
4bd2feda7d | ||
|
|
bcf699f145 | ||
|
|
d4f29491c9 | ||
|
|
5b1c932f89 | ||
|
|
7a8d6e44e3 | ||
|
|
dac349397e | ||
|
|
5ff7e7f9a1 | ||
|
|
7b2ab822c6 | ||
|
|
033260300a | ||
|
|
cb66b54f8b | ||
|
|
f4a8102a80 | ||
|
|
8f539f17b2 | ||
|
|
e5c543a0a1 | ||
|
|
7d697faf95 | ||
|
|
6f23151a5e | ||
|
|
e53c7ed8d1 | ||
|
|
dcd44a0edf | ||
|
|
f0a5ea9d0f | ||
|
|
491b513aa3 | ||
|
|
d5872bba66 | ||
|
|
c4f4edda1b | ||
|
|
cf057b6631 | ||
|
|
2a7a157713 | ||
|
|
7463fe511b | ||
|
|
1b724daa10 | ||
|
|
888d3b6250 | ||
|
|
289afbf0a6 | ||
|
|
9b89bee4f5 | ||
|
|
3f8f488a58 | ||
|
|
592d47e971 | ||
|
|
4732012f1c | ||
|
|
7683325d68 | ||
|
|
03d665e243 | ||
|
|
a1591da25d | ||
|
|
1f1e1209d2 | ||
|
|
a389905a38 | ||
|
|
36dd6b07d1 | ||
|
|
2f3689713b | ||
|
|
819fab7b58 | ||
|
|
e5ca1f37f1 | ||
|
|
c3650ea7c7 | ||
|
|
1805337424 | ||
|
|
27bb6ebac1 | ||
|
|
580323c221 | ||
|
|
d9286c549f | ||
|
|
26dfa6d257 | ||
|
|
483d4ab3c3 | ||
|
|
663dfe5932 | ||
|
|
ce9c752899 | ||
|
|
d5e7bc9fd6 | ||
|
|
744e765d6f | ||
|
|
29551ba4f3 | ||
|
|
bd9a3b2305 | ||
|
|
c8c3325b56 | ||
|
|
84c7e2b21b | ||
|
|
dda25bb29e | ||
|
|
9ccf2ef96b | ||
|
|
c6fa55bfc8 | ||
|
|
06bcf1c2e1 | ||
|
|
40f402d117 | ||
|
|
71f6a95ce5 | ||
|
|
5cd7d47f72 | ||
|
|
d0fe5c4712 | ||
|
|
f602c4911c | ||
|
|
7aaf7eaf30 | ||
|
|
35f16e8125 | ||
|
|
acc777c267 | ||
|
|
1c74356691 | ||
|
|
bbebea0fa5 | ||
|
|
66eb27b0af | ||
|
|
7a63c06a65 | ||
|
|
554dfd4923 | ||
|
|
36a6e2aa1d | ||
|
|
3c4b73f136 | ||
|
|
bc3ed74336 | ||
|
|
97b6f33cc2 | ||
|
|
a9889ddb31 | ||
|
|
cd1b7ce9c7 | ||
|
|
3653d6e0ef | ||
|
|
c3387f8dbf | ||
|
|
3d54184c7f | ||
|
|
6f23e706d7 | ||
|
|
cc69edf92c | ||
|
|
ba7560f65e | ||
|
|
c3960c4a96 | ||
|
|
5c21f94bb1 | ||
|
|
8cd7c94490 | ||
|
|
6a6fa7b29a | ||
|
|
4984548cab | ||
|
|
6941bde7e2 | ||
|
|
1504f25ced | ||
|
|
99e350ac85 | ||
|
|
1624b07589 | ||
|
|
d06dce4614 | ||
|
|
03098e81f8 | ||
|
|
726c152f6e | ||
|
|
409d2e29e5 | ||
|
|
01e2bd5050 | ||
|
|
96033e38ea | ||
|
|
ed75290ef7 | ||
|
|
a14dbf012a | ||
|
|
17c11ba7b9 | ||
|
|
2a1daca1ca | ||
|
|
f0db5ce350 | ||
|
|
39f9c2e1a0 | ||
|
|
bff612a169 | ||
|
|
4ba42f3746 | ||
|
|
58bee05c36 | ||
|
|
c1871b0f0c | ||
|
|
c16974b091 | ||
|
|
bfedda9764 | ||
|
|
a67b7276be | ||
|
|
47f3105ef0 | ||
|
|
aeb56539c9 | ||
|
|
75d45efa16 | ||
|
|
59d1c5bebb | ||
|
|
040983c979 | ||
|
|
2ddb344bac | ||
|
|
e56bd3918b | ||
|
|
59600a1c29 | ||
|
|
f8e4ea868f | ||
|
|
0ff56c53b1 | ||
|
|
b617d983de | ||
|
|
8e0f0e8e8c | ||
|
|
d745d6b5f0 | ||
|
|
fc2c2a477d | ||
|
|
ff93277c0f | ||
|
|
90741b3cee | ||
|
|
d1de59f0ed | ||
|
|
73f8e001ad | ||
|
|
390cc45af2 | ||
|
|
33118ac6e2 | ||
|
|
31ff9a300c | ||
|
|
5cc739d879 | ||
|
|
1e7f07259e | ||
|
|
c36a5cfd96 | ||
|
|
299fd1f770 | ||
|
|
656427d328 | ||
|
|
621522fdd4 | ||
|
|
6e3589bf52 | ||
|
|
df2d9b282e | ||
|
|
726d35c5c5 | ||
|
|
f509078020 | ||
|
|
8308515210 | ||
|
|
ed838b3cbf | ||
|
|
04fac300e8 | ||
|
|
ff237f4b66 | ||
|
|
e42e3d9e00 | ||
|
|
61505f4c59 | ||
|
|
86eddb05b4 | ||
|
|
8af5509581 | ||
|
|
166e5f4d6c | ||
|
|
6ad8d20694 | ||
|
|
cbc03feb52 | ||
|
|
bc3a495160 | ||
|
|
b323631611 | ||
|
|
e8767ba660 | ||
|
|
af9a4114f4 | ||
|
|
75f97961f5 | ||
|
|
25a7168286 | ||
|
|
494e81f436 | ||
|
|
169a2a8ad2 | ||
|
|
b267029301 | ||
|
|
cf574634b8 | ||
|
|
f8c01574e6 | ||
|
|
481f1e7c5c | ||
|
|
5e650953cd | ||
|
|
ed5e902106 | ||
|
|
87f9ab29df | ||
|
|
47c64a86d5 | ||
|
|
bb497beeff | ||
|
|
e14d9c4be3 | ||
|
|
89e0b35c53 | ||
|
|
1e7b68236b | ||
|
|
394068f863 | ||
|
|
b831e81074 | ||
|
|
4c13c2b00b | ||
|
|
dd98a45003 | ||
|
|
fe6762b470 | ||
|
|
fa16b74500 | ||
|
|
4cd190b232 | ||
|
|
6ada55ff77 | ||
|
|
735ce6f758 | ||
|
|
430324885b | ||
|
|
7c2e8ce7ca | ||
|
|
d4025999b7 | ||
|
|
871111424d | ||
|
|
44f331f43d | ||
|
|
213144413f | ||
|
|
2272f9aead | ||
|
|
59848ca151 | ||
|
|
c14bfe3e5f | ||
|
|
26c48ab324 | ||
|
|
4c8d57e14c | ||
|
|
543689e206 | ||
|
|
ee524831f4 | ||
|
|
cfecab9f79 | ||
|
|
b3d9435dbb | ||
|
|
fec8dd37b0 | ||
|
|
0690500a0d | ||
|
|
0bfbda720d | ||
|
|
4fcdbd39fb | ||
|
|
f934e6d816 | ||
|
|
79c6bbc189 | ||
|
|
2e80ec0c22 | ||
|
|
588283cfe5 | ||
|
|
3a43871901 | ||
|
|
fcbab02b2d | ||
|
|
5f3475342e | ||
|
|
e022e6199c | ||
|
|
140c12e8fc | ||
|
|
21f25972bb | ||
|
|
d0e1bd96fb | ||
|
|
6c56ebc984 | ||
|
|
d0a9931ae6 | ||
|
|
93c5f654d9 | ||
|
|
d8b65028a1 | ||
|
|
d6cdc1841c | ||
|
|
72b39220e5 | ||
|
|
55dce7d119 | ||
|
|
789736dd02 | ||
|
|
c7ca3b0101 | ||
|
|
96000220b1 | ||
|
|
e2e2275d41 | ||
|
|
135ff20123 | ||
|
|
4af86f5398 | ||
|
|
e5e0e6481d | ||
|
|
bcf69b86b4 | ||
|
|
a5f79fac81 | ||
|
|
18a00822c5 | ||
|
|
4cc8437f79 | ||
|
|
8e58305b0a | ||
|
|
bd368aceee | ||
|
|
8f16021887 | ||
|
|
bbb1b69b2e | ||
|
|
9ea8a2096f | ||
|
|
66340e2b19 | ||
|
|
fe29dfa89c | ||
|
|
41f7fabe2f | ||
|
|
856a040a2d | ||
|
|
f7eaa5ec29 | ||
|
|
0c87d47318 | ||
|
|
c24b2f5a73 | ||
|
|
774c83a36e | ||
|
|
751cf6ab5b | ||
|
|
2fd76c954c | ||
|
|
bb4d18f959 |
@@ -4,25 +4,17 @@
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
node18:
|
||||
node24:
|
||||
docker:
|
||||
- image: cimg/node:18.0.0 # Latest 18.x
|
||||
- image: cimg/node:24.0.0
|
||||
working_directory: ~/workspace
|
||||
node16:
|
||||
node22:
|
||||
docker:
|
||||
- image: cimg/node:16.14.2 # Latest 16.x
|
||||
- image: cimg/node:22.0.0
|
||||
working_directory: ~/workspace
|
||||
node14:
|
||||
node20:
|
||||
docker:
|
||||
- image: cimg/node:14.17.4 # Latest 14.x
|
||||
working_directory: ~/workspace
|
||||
node12_latest:
|
||||
docker:
|
||||
- image: cimg/node:12.22.10 # Latest 12.x
|
||||
working_directory: ~/workspace
|
||||
node12_17:
|
||||
docker:
|
||||
- image: cimg/node:12.17.0 # Oldest version supported by Jasmine
|
||||
- image: cimg/node:20.0.0
|
||||
working_directory: ~/workspace
|
||||
|
||||
jobs:
|
||||
@@ -59,20 +51,34 @@ jobs:
|
||||
name: Run tests
|
||||
command: npm test
|
||||
|
||||
test_parallel: &test_parallel
|
||||
parameters:
|
||||
executor:
|
||||
type: executor
|
||||
executor: << parameters.executor >>
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Run tests in parallel
|
||||
command: npm run test:parallel
|
||||
|
||||
test_browsers: &test_browsers
|
||||
executor: node14
|
||||
executor: node20
|
||||
steps:
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Install Sauce Connect
|
||||
command: |
|
||||
cd /tmp
|
||||
curl https://saucelabs.com/downloads/sc-4.7.1-linux.tar.gz | tar zxf -
|
||||
chmod +x sc-4.7.1-linux/bin/sc
|
||||
tmpdir=$(mktemp -d)
|
||||
cd "$tmpdir"
|
||||
curl https://saucelabs.com/downloads/sauce-connect/5.2.2/sauce-connect-5.2.2_linux.x86_64.tar.gz | tar zxf -
|
||||
chmod +x sc
|
||||
mkdir ~/workspace/bin
|
||||
cp sc-4.7.1-linux/bin/sc ~/workspace/bin
|
||||
~/workspace/bin/sc --version
|
||||
cp sc ~/workspace/bin
|
||||
echo "Sauce Connect version info:"
|
||||
~/workspace/bin/sc version
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
@@ -80,13 +86,13 @@ jobs:
|
||||
# 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
|
||||
export SAUCE_TUNNEL_NAME=$CIRCLE_WORKFLOW_JOB_ID
|
||||
scripts/start-sauce-connect
|
||||
set +o errexit
|
||||
scripts/run-all-browsers
|
||||
exitcode=$?
|
||||
set -o errexit
|
||||
scripts/stop-sauce-connect $(cat sauce-pidfile)
|
||||
scripts/stop-sauce-connect
|
||||
exit $exitcode
|
||||
|
||||
workflows:
|
||||
@@ -95,48 +101,47 @@ workflows:
|
||||
push:
|
||||
jobs:
|
||||
- build:
|
||||
executor: node18
|
||||
name: build_node_18
|
||||
executor: node24
|
||||
name: build_node_24
|
||||
- build:
|
||||
executor: node16
|
||||
name: build_node_16
|
||||
executor: node22
|
||||
name: build_node_22
|
||||
- build:
|
||||
executor: node14
|
||||
name: build_node_14
|
||||
- build:
|
||||
executor: node12_latest
|
||||
name: build_node_12_latest
|
||||
- build:
|
||||
executor: node12_17
|
||||
name: build_node_12_17
|
||||
executor: node20
|
||||
name: build_node_20
|
||||
- test_node:
|
||||
executor: node18
|
||||
name: test_node_18
|
||||
executor: node22
|
||||
name: test_node_22
|
||||
requires:
|
||||
- build_node_18
|
||||
- build_node_22
|
||||
- test_node:
|
||||
executor: node16
|
||||
name: test_node_16
|
||||
executor: node20
|
||||
name: test_node_20
|
||||
requires:
|
||||
- build_node_16
|
||||
- test_node:
|
||||
executor: node14
|
||||
name: test_node_14
|
||||
- build_node_20
|
||||
- test_parallel:
|
||||
executor: node24
|
||||
name: test_parallel_node_24
|
||||
requires:
|
||||
- build_node_14
|
||||
- test_node:
|
||||
executor: node12_latest
|
||||
name: test_node_12_latest
|
||||
- build_node_24
|
||||
- test_parallel:
|
||||
executor: node22
|
||||
name: test_parallel_node_22
|
||||
requires:
|
||||
- build_node_12_latest
|
||||
- test_node:
|
||||
executor: node12_17
|
||||
name: test_node_12_17
|
||||
- build_node_22
|
||||
- test_parallel:
|
||||
executor: node20
|
||||
name: test_parallel_node_20
|
||||
requires:
|
||||
- build_node_12_17
|
||||
- build_node_20
|
||||
- test_parallel:
|
||||
executor: node20
|
||||
name: test_parallel_node_20
|
||||
requires:
|
||||
- build_node_20
|
||||
- test_browsers:
|
||||
requires:
|
||||
- build_node_14
|
||||
- build_node_20
|
||||
filters:
|
||||
branches:
|
||||
ignore: /pull\/.*/ # Don't run on pull requests.
|
||||
|
||||
@@ -3,6 +3,6 @@ charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
|
||||
[*.{js, json, sh, yml}]
|
||||
[*.{js,mjs,json,sh,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
31
.github/CONTRIBUTING.md
vendored
31
.github/CONTRIBUTING.md
vendored
@@ -1,19 +1,10 @@
|
||||
# Developing for Jasmine Core
|
||||
# Contributing to Jasmine
|
||||
|
||||
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)
|
||||
for everyone. If you want to contribute but don't know what to work on,
|
||||
[issues tagged help needed](https://github.com/issues?q=is%3Aopen+is%3Aissue+org%3Ajasmine+label%3A%22help+needed%22+)
|
||||
should have enough detail to get started.
|
||||
|
||||
## Links
|
||||
|
||||
- [Jasmine Google Group](http://groups.google.com/group/jasmine-js)
|
||||
- [Jasmine-dev Google Group](http://groups.google.com/group/jasmine-js-dev)
|
||||
- [Jasmine backlog](https://www.pivotaltracker.com/n/projects/10606)
|
||||
|
||||
## Before Submitting a Pull Request
|
||||
|
||||
1. Ensure all specs are green in browsers *and* node.
|
||||
@@ -94,14 +85,7 @@ Or, How to make a successful pull request
|
||||
* _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.
|
||||
|
||||
Key exceptions:
|
||||
* Use `const` or `let` for new variable declarations, even if nearby code
|
||||
uses `var`.
|
||||
* New async specs should usually be async/await or promise-returning, not
|
||||
callback based.
|
||||
|
||||
a cohesive whole.
|
||||
* _Ensure the *entire* test suite is green_ in all the big browsers, Node, and
|
||||
ESLint/Prettier. Your contribution shouldn't break Jasmine for other users.
|
||||
|
||||
@@ -119,3 +103,10 @@ chromedriver), you can also use Jasmine's CI tooling:
|
||||
|
||||
$ JASMINE_BROWSER=<name of browser> npm run ci
|
||||
|
||||
### Submitting a Pull Requeset
|
||||
|
||||
Once you've done the steps listed under "Before Submitting a Pull Request"
|
||||
above, you can submit a pull request via the
|
||||
[standard GitHub process](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
|
||||
TL;DR: Fork the repository, push your work up to your fork, and create a PR from
|
||||
there.
|
||||
|
||||
47
.github/ISSUE_TEMPLATE.md
vendored
47
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,47 +0,0 @@
|
||||
## Are you creating an issue in the correct repository?
|
||||
|
||||
- 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)
|
||||
- [Karma](https://github.com/karma-runner/karma/issues)
|
||||
- [Grunt Contrib Jasmine](https://github.com/gruntjs/grunt-contrib-jasmine/issues)
|
||||
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
|
||||
## Expected Behavior
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||
|
||||
## Current Behavior
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
|
||||
## Possible Solution
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
|
||||
## Suite that reproduces the behavior (for bugs)
|
||||
<!--- Provide a sample suite that reproduces the bug. -->
|
||||
```javascript
|
||||
describe("sample", function() {
|
||||
});
|
||||
```
|
||||
## Context
|
||||
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
|
||||
|
||||
## Your Environment
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
* Version used:
|
||||
* Environment name and version (e.g. Chrome 39, node.js 5.4):
|
||||
* Operating System and version (desktop or mobile):
|
||||
* Link to your project:
|
||||
95
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
95
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
name: Bug Report
|
||||
description: I think I've found a bug in Jasmine
|
||||
labels: ["bug report"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report a bug. Please follow these steps first.
|
||||
|
||||
## Troubleshooting
|
||||
Please take the time to rule out issues with your code or third party libraries before filing a bug report. If you are reporting an error, try to determine whether the error is coming from Jasmine, another library, or your own code.
|
||||
|
||||
Check the [FAQ](https://jasmine.github.io/pages/faq.html) and any other relevant [documentation](https://jasmine.github.io/pages/docs_home.html) to see if your issue has already been addressed.
|
||||
|
||||
## Special troubleshooting steps for asynchronous scenarios
|
||||
If the issue has to do with testing asynchronous code, please read the [async tutorial](https://jasmine.github.io/tutorials/async) and the [async section of the FAQ](https://jasmine.github.io/pages/faq.html#async). In particular, check for the following common errors:
|
||||
|
||||
* Are you trying to write a synchronous test for asynchronous code?
|
||||
* Does the test signal completion before the code under test finishes?
|
||||
* Do expectations run before the code that they're trying to verify?
|
||||
|
||||
## Try the latest version of Jasmine
|
||||
If at all possible, upgrade to the latest versions of `jasmine-core` and any other relevant packages (e.g. `jasmine`, `jasmine-browser-runner`). If you can't do that, please check the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes) for all newer versions to make sure that the bug hasn't already been fixed.
|
||||
|
||||
## Explain how to reproduce the bug
|
||||
|
||||
**Working steps to reproduce are required for all bug reports.** Please help us help you by creating complete but minimal instructions for reproducing the bug.
|
||||
|
||||
The steps to reproduce could be:
|
||||
|
||||
* A code snippet that reproduces the problem when run by itself in a newly generated empty `jasmine` or `jasmine-browser-runner` project, or in the standalone distribution.
|
||||
* A set of steps that reproduce the problem when followed exactly as they're written in an empty directory.
|
||||
* A link to a Git repository or zip/tar file containing a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). This option is required for all bugs that can only be reproduced with third-party libraries, including Angular and Karma.
|
||||
|
||||
Please **test your steps** by starting with an empty directory and following them exactly as they're written. Bug reports with steps to reproduce that are unclear, don't work, or include an unreasonable amount of extraneous code will likely be closed.
|
||||
|
||||
- type: textarea
|
||||
id: steps-to-reproduce
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What do you think should have happened?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: actual-behavior
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What happened instead?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: possible-solution
|
||||
attributes:
|
||||
label: Possible Solution
|
||||
description: This is optional, but if you have an idea for how to fix the bug we'd like to hear it.
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Context
|
||||
description: How has this issue affected you? What are you trying to accomplish? By providing context, you can help us come up with a solution that is most useful in the real world.
|
||||
- type: input
|
||||
id: jasmine-core-version
|
||||
attributes:
|
||||
label: jasmine-core version
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: other-versions
|
||||
attributes:
|
||||
label: Versions of other relevant packages
|
||||
placeholder: |
|
||||
jasmine-browser-runner 1.2.0
|
||||
fancy-reporter 132.4.8
|
||||
|
||||
- type: input
|
||||
id: browser-or-node-version
|
||||
attributes:
|
||||
label: Node.js and/or browser version
|
||||
placeholder: E.g. "node 16.2.0" or "Safari 15"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
placeholder: E.g. "Windows 10", "MacOS 12.5", "MCC Interim Linux 0.99.p8"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Questions, requests for help, etc
|
||||
url: https://github.com/jasmine/jasmine/discussions/new/choose
|
||||
about: Please start a discussion.
|
||||
- name: Issues with the `jasmine` CLI
|
||||
url: https://github.com/jasmine/jasmine-npm/issues
|
||||
about: Please create issues related to the `jasmine` package in its repository.
|
||||
- name: Issues with jasmine-browser-runner
|
||||
url: https://github.com/jasmine/jasmine-browser-runner/issues
|
||||
about: Please create issues related to the `jasmine-browser-runner` package in its repository.
|
||||
- name: Documentation issues
|
||||
url: https://github.com/jasmine/jasmine.github.io/issues
|
||||
about: Please create documentation issues in the docs repository.
|
||||
- name: TypeScript issues
|
||||
url: https://github.com/DefinitelyTyped/DefinitelyTyped/discussions
|
||||
about: Please create issues related to TypeScript compilation errors or other problems with type definitions at DefinitelyTyped.
|
||||
31
.github/ISSUE_TEMPLATE/feature_proposal.yml
vendored
Normal file
31
.github/ISSUE_TEMPLATE/feature_proposal.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Feature Proposal
|
||||
description: I'd like to propose a new feature
|
||||
labels: ["feature request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: Thanks for taking the time to propose a new feature. Although Jasmine is mostly feature complete, we're always open to hearing new ideas.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Feature Proposal
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Context
|
||||
description: How would this feature be useful to you? What are you trying to accomplish? By providing context, you can help us come up with a solution that is most useful in the real world.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: example
|
||||
attributes:
|
||||
label: Example
|
||||
description: If you're proposing a new API or something similar, please show an example of how it would be used.
|
||||
render: JavaScript
|
||||
- type: textarea
|
||||
id: other-info
|
||||
attributes:
|
||||
label: Other Information
|
||||
description: Anything else that you think would be helpful.
|
||||
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
66
Gruntfile.js
66
Gruntfile.js
@@ -1,66 +0,0 @@
|
||||
module.exports = function(grunt) {
|
||||
var pkg = require("./package.json");
|
||||
global.jasmineVersion = pkg.version;
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: pkg,
|
||||
concat: require('./grunt/config/concat.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', ['sass:dist', "cssUrlEmbed"]);
|
||||
|
||||
grunt.registerTask('buildDistribution',
|
||||
'Builds and lints jasmine.js, jasmine-html.js, jasmine.css',
|
||||
[
|
||||
'sass:dist',
|
||||
"cssUrlEmbed",
|
||||
'concat'
|
||||
]
|
||||
);
|
||||
|
||||
grunt.registerTask("execSpecsInNode",
|
||||
"Run Jasmine core specs in Node.js",
|
||||
function() {
|
||||
verifyNoGlobals(() => require('./lib/jasmine-core.js').noGlobals());
|
||||
const done = this.async(),
|
||||
Jasmine = require('jasmine'),
|
||||
jasmineCore = require('./lib/jasmine-core.js'),
|
||||
jasmine = new Jasmine({jasmineCore: jasmineCore});
|
||||
|
||||
jasmine.loadConfigFile('./spec/support/jasmine.json');
|
||||
jasmine.exitOnCompletion = false;
|
||||
jasmine.execute().then(
|
||||
result => done(result.overallStatus === 'passed'),
|
||||
err => {
|
||||
console.error(err);
|
||||
exit(1);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
grunt.registerTask("execSpecsInNode:performance",
|
||||
"Run Jasmine performance specs in Node.js",
|
||||
function() {
|
||||
require("shelljs").exec("node_modules/.bin/jasmine JASMINE_CONFIG_PATH=spec/support/jasmine-performance.json");
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
function verifyNoGlobals(fn) {
|
||||
const initialGlobals = Object.keys(global);
|
||||
fn();
|
||||
|
||||
const extras = Object.keys(global).filter(k => !initialGlobals.includes(k));
|
||||
|
||||
if (extras.length !== 0) {
|
||||
throw new Error('Globals were unexpectedly created: ' + extras.join(', '));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
Copyright (c) 2008-2019 Pivotal Labs
|
||||
Copyright (c) 2008-2025 The Jasmine developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
48
README.md
48
README.md
@@ -1,18 +1,10 @@
|
||||
<a name="README">[<img src="https://rawgithub.com/jasmine/jasmine/main/images/jasmine-horizontal.svg" width="400px" />](http://jasmine.github.io)</a>
|
||||
|
||||
[](https://circleci.com/gh/jasmine/jasmine)
|
||||
[](https://www.codetriage.com/jasmine/jasmine)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_shield)
|
||||
<a name="README"><img src="https://raw.githubusercontent.com/jasmine/jasmine/main/images/jasmine-horizontal.svg" width="400px" alt="Jasmine"></a>
|
||||
|
||||
# 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, see the beginning of [http://jasmine.github.io/edge/introduction.html](http://jasmine.github.io/edge/introduction.html).
|
||||
|
||||
Upgrading from Jasmine 3.x? Check out the 4.0 release notes for a list of
|
||||
what's new (including breaking changes). You can also read the [upgrade guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_4.0).
|
||||
Upgrading from Jasmine 4.x? Check out the [upgrade guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_5.0).
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -28,34 +20,30 @@ for details.
|
||||
|
||||
See the [documentation site](https://jasmine.github.io/pages/docs_home.html),
|
||||
particularly the [Your First Suite tutorial](https://jasmine.github.io/tutorials/your_first_suite)
|
||||
for information on writing specs.
|
||||
for information on writing specs, and [the FAQ](https://jasmine.github.io/pages/faq.html).
|
||||
|
||||
## Supported environments
|
||||
|
||||
Jasmine tests itself across popular browsers (Safari, Chrome, Firefox, and
|
||||
Microsoft Edge) as well as Node.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-15 |
|
||||
| Chrome | Evergreen |
|
||||
| Firefox | Evergreen, 91 |
|
||||
| Edge | Evergreen |
|
||||
| Environment | Supported versions |
|
||||
|-------------------|----------------------------------|
|
||||
| Node | 20, 22, 24 |
|
||||
| Safari | 16*, 17* |
|
||||
| Chrome | Evergreen |
|
||||
| Firefox | Evergreen, 102*, 115*, 128*, 140 |
|
||||
| Edge | Evergreen |
|
||||
|
||||
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.
|
||||
|
||||
See the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes)
|
||||
for the supported environments for each Jasmine release.
|
||||
\* Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
## 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).
|
||||
To find out what environments work with a particular Jasmine release, see the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes).
|
||||
|
||||
## Maintainers
|
||||
|
||||
@@ -71,8 +59,6 @@ for the supported environments for each Jasmine release.
|
||||
* [Christian Williams](mailto:antixian666@gmail.com)
|
||||
* Sheel Choksi
|
||||
|
||||
Copyright (c) 2008-2022 Jasmine Maintainers. This software is licensed under the MIT License.
|
||||
|
||||
|
||||
## License
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fjasmine%2Fjasmine?ref=badge_large)
|
||||
Copyright (c) 2008-2019 Pivotal Labs<br>
|
||||
Copyright (c) 2008-2025 The Jasmine developers<br>
|
||||
This software is licensed under the [MIT License](https://github.com/jasmine/jasmine/blob/main/LICENSE).
|
||||
|
||||
51
RELEASE.md
51
RELEASE.md
@@ -18,12 +18,11 @@ copied to `jasmine.js` when the distribution is built. When releasing a new
|
||||
version, update `package.json` with the new version and `npm run build` to
|
||||
update the gem version number.
|
||||
|
||||
Note that Jasmine should only use the "patch" version number in the following cases:
|
||||
Note that Jasmine should only use the "patch" version number if the new release
|
||||
contains only bug fixes.
|
||||
|
||||
* Changes related to packaging for a specific binding library (npm or browser-runner)
|
||||
* Fixes for regressions.
|
||||
|
||||
When jasmine-core revs its major or minor version, the binding libraries should also rev to that version.
|
||||
When `jasmine-core` revs its major or minor version, the `jasmine` NPM package
|
||||
should also rev to that version.
|
||||
|
||||
## Release
|
||||
|
||||
@@ -35,46 +34,34 @@ When ready to release - specs are all green and the stories are done:
|
||||
|
||||
### Commit and push core changes
|
||||
|
||||
1. Run the browser tests using `scripts/run-all-browsers`.
|
||||
1. Commit release notes and version changes (jasmine.js, package.json)
|
||||
1. Push
|
||||
1. Wait for Circle CI to go green
|
||||
2. Push
|
||||
3. Tag the release and push the tag.
|
||||
4. Wait for Circle CI to go green
|
||||
|
||||
### Build standalone distribution
|
||||
|
||||
1. Build the standalone distribution with `grunt buildStandaloneDist`
|
||||
1. Build the standalone distribution with `npm run buildStandaloneDist`
|
||||
1. This will generate `dist/jasmine-standalone-<version>.zip`, which you will upload later (see "Finally" below).
|
||||
|
||||
### 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`
|
||||
1. `npm login` to save your credentials locally
|
||||
2. `npm publish .` to publish what's in `package.json`
|
||||
|
||||
### Release the docs
|
||||
|
||||
Probably only need to do this when releasing a minor version, and not a patch version.
|
||||
Probably only need to do this when releasing a minor version, and not a patch
|
||||
version. See [the README file in the docs repo](https://github.com/jasmine/jasmine.github.io/blob/master/README.md)
|
||||
for instructions.
|
||||
|
||||
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 `jasmine` NPM package
|
||||
|
||||
### Release the binding libraries
|
||||
See <https://github.com/jasmine/jasmine-npm/blob/main/RELEASE.md>.
|
||||
|
||||
#### NPM
|
||||
### Publish the GitHub release
|
||||
|
||||
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`.)
|
||||
|
||||
### Finally
|
||||
|
||||
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.
|
||||
2. Paste in a link to the correct release notes for this release.
|
||||
3. If it is a pre-release, mark it as such.
|
||||
4. Attach the standalone zipfile.
|
||||
|
||||
56
eslint.config.mjs
Normal file
56
eslint.config.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
import { defineConfig } from "eslint/config";
|
||||
import globals from "globals";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import js from "@eslint/js";
|
||||
import { FlatCompat } from "@eslint/eslintrc";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
});
|
||||
|
||||
export default defineConfig([{
|
||||
extends: compat.extends("plugin:compat/recommended"),
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.node,
|
||||
},
|
||||
|
||||
// 2022 isn't exactly right, but it's the earliest version that allows
|
||||
// private properties.
|
||||
ecmaVersion: 2022,
|
||||
sourceType: "commonjs",
|
||||
},
|
||||
|
||||
rules: {
|
||||
curly: "error",
|
||||
|
||||
quotes: ["error", "single", {
|
||||
avoidEscape: true,
|
||||
}],
|
||||
|
||||
"no-unused-vars": ["error", {
|
||||
args: "none",
|
||||
}],
|
||||
|
||||
"no-implicit-globals": "error",
|
||||
"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",
|
||||
"no-eval": "error",
|
||||
"no-var": "error",
|
||||
"no-debugger": "error",
|
||||
"no-console": "error",
|
||||
},
|
||||
}]);
|
||||
@@ -1,57 +0,0 @@
|
||||
var standaloneLibDir = "lib/jasmine-" + jasmineVersion;
|
||||
|
||||
function root(path) { return "./" + path; }
|
||||
function libJasmineCore(path) { return root("lib/jasmine-core/" + path); }
|
||||
function dist(path) { return root("dist/" + path); }
|
||||
|
||||
module.exports = {
|
||||
standalone: {
|
||||
options: {
|
||||
archive: root("dist/jasmine-standalone-" + global.jasmineVersion + ".zip")
|
||||
},
|
||||
|
||||
files: [
|
||||
{ src: [ root("MIT.LICENSE") ] },
|
||||
{
|
||||
src: [ "jasmine_favicon.png"],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: root("images")
|
||||
},
|
||||
{
|
||||
src: [
|
||||
"jasmine.js",
|
||||
"jasmine-html.js",
|
||||
"jasmine.css"
|
||||
],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: libJasmineCore("")
|
||||
},
|
||||
{
|
||||
src: [ "boot0.js", "boot1.js" ],
|
||||
dest: standaloneLibDir,
|
||||
expand: true,
|
||||
cwd: libJasmineCore("")
|
||||
},
|
||||
{
|
||||
src: [ "SpecRunner.html" ],
|
||||
dest: root(""),
|
||||
expand: true,
|
||||
cwd: dist("tmp")
|
||||
},
|
||||
{
|
||||
src: [ "*.js" ],
|
||||
dest: "src",
|
||||
expand: true,
|
||||
cwd: libJasmineCore("example/src/")
|
||||
},
|
||||
{
|
||||
src: [ "*.js" ],
|
||||
dest: "spec",
|
||||
expand: true,
|
||||
cwd: libJasmineCore("example/spec/")
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
var grunt = require('grunt');
|
||||
|
||||
function license() {
|
||||
var currentYear = "" + new Date(Date.now()).getFullYear();
|
||||
|
||||
return grunt.template.process(
|
||||
grunt.file.read("grunt/templates/licenseBanner.js.jst"),
|
||||
{ data: { currentYear: currentYear}});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
'jasmine-html': {
|
||||
src: [
|
||||
'src/html/requireHtml.js',
|
||||
'src/html/HtmlReporter.js',
|
||||
'src/html/HtmlSpecFilter.js',
|
||||
'src/html/ResultsNode.js',
|
||||
'src/html/QueryString.js',
|
||||
'src/html/**/*.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine-html.js'
|
||||
},
|
||||
jasmine: {
|
||||
src: [
|
||||
'src/core/requireCore.js',
|
||||
'src/core/matchers/requireMatchers.js',
|
||||
'src/core/base.js',
|
||||
'src/core/util.js',
|
||||
'src/core/Spec.js',
|
||||
'src/core/Order.js',
|
||||
'src/core/Env.js',
|
||||
'src/core/JsApiReporter.js',
|
||||
'src/core/PrettyPrinter',
|
||||
'src/core/Suite',
|
||||
'src/core/**/*.js',
|
||||
'src/version.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine.js'
|
||||
},
|
||||
boot0: {
|
||||
src: ['src/boot/boot0.js'],
|
||||
dest: 'lib/jasmine-core/boot0.js'
|
||||
},
|
||||
boot1: {
|
||||
src: ['src/boot/boot1.js'],
|
||||
dest: 'lib/jasmine-core/boot1.js'
|
||||
},
|
||||
nodeBoot: {
|
||||
src: ['src/boot/node_boot.js'],
|
||||
dest: 'lib/jasmine-core/node_boot.js'
|
||||
},
|
||||
options: {
|
||||
banner: license(),
|
||||
process: {
|
||||
data: {
|
||||
version: global.jasmineVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
module.exports = {
|
||||
encodeWithBaseDir: {
|
||||
files: {
|
||||
"lib/jasmine-core/jasmine.css": ["lib/jasmine-core/jasmine.css"]
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
const sass = require('sass');
|
||||
|
||||
module.exports = {
|
||||
options: {
|
||||
implementation: sass,
|
||||
sourceComments: false
|
||||
},
|
||||
dist: {
|
||||
files: {
|
||||
"lib/jasmine-core/jasmine.css": "src/html/jasmine.scss"
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
var grunt = require("grunt");
|
||||
|
||||
function standaloneTmpDir(path) { return "dist/tmp/" + path; }
|
||||
|
||||
grunt.registerTask("build:compileSpecRunner",
|
||||
"Processes the spec runner template and writes to a tmp file",
|
||||
function() {
|
||||
var runnerHtml = grunt.template.process(
|
||||
grunt.file.read("grunt/templates/SpecRunner.html.jst"),
|
||||
{ data: { jasmineVersion: global.jasmineVersion }});
|
||||
|
||||
grunt.file.write(standaloneTmpDir("SpecRunner.html"), runnerHtml);
|
||||
}
|
||||
);
|
||||
|
||||
grunt.registerTask("build:cleanSpecRunner",
|
||||
"Deletes the tmp spec runner file",
|
||||
function() {
|
||||
grunt.file.delete(standaloneTmpDir(""));
|
||||
}
|
||||
);
|
||||
|
||||
grunt.registerTask("buildStandaloneDist",
|
||||
"Builds a standalone distribution",
|
||||
[
|
||||
"buildDistribution",
|
||||
"build:compileSpecRunner",
|
||||
"compress:standalone",
|
||||
"build:cleanSpecRunner"
|
||||
]
|
||||
);
|
||||
@@ -1,3 +1,27 @@
|
||||
/*
|
||||
Copyright (c) 2008-2019 Pivotal Labs
|
||||
Copyright (c) 2008-2025 The Jasmine developers
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: Only available on Node.
|
||||
* @module jasmine-core
|
||||
@@ -6,68 +30,83 @@
|
||||
const jasmineRequire = require('./jasmine-core/jasmine.js');
|
||||
module.exports = jasmineRequire;
|
||||
|
||||
const bootWithoutGlobals = (function() {
|
||||
let jasmine, jasmineInterface;
|
||||
|
||||
return function bootWithoutGlobals(reinitialize) {
|
||||
if (!jasmineInterface || reinitialize === true) {
|
||||
jasmine = jasmineRequire.core(jasmineRequire);
|
||||
const env = jasmine.getEnv({ suppressLoadErrors: true });
|
||||
jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
}
|
||||
|
||||
return { jasmine, jasmineInterface };
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Boots a copy of Jasmine and returns an object as described in {@link jasmine}.
|
||||
* @param {boolean} [reinitialize=true] Whether to create a new copy of Jasmine if one already exists
|
||||
* @type {function}
|
||||
* @return {jasmine}
|
||||
*/
|
||||
module.exports.boot = require('./jasmine-core/node_boot.js');
|
||||
module.exports.boot = function(reinitialize) {
|
||||
if (reinitialize === undefined) {
|
||||
reinitialize = true;
|
||||
}
|
||||
|
||||
const { jasmine, jasmineInterface } = bootWithoutGlobals(reinitialize);
|
||||
|
||||
for (const k in jasmineInterface) {
|
||||
global[k] = jasmineInterface[k];
|
||||
}
|
||||
|
||||
return jasmine;
|
||||
};
|
||||
|
||||
/**
|
||||
* Boots a copy of Jasmine and returns an object containing the properties
|
||||
* that would normally be added to the global object. If noGlobals is called
|
||||
* multiple times, the same object is returned every time.
|
||||
*
|
||||
* Do not call boot() if you also call noGlobals().
|
||||
*
|
||||
* @example
|
||||
* const {describe, beforeEach, it, expect, jasmine} = require('jasmine-core').noGlobals();
|
||||
*/
|
||||
module.exports.noGlobals = (function() {
|
||||
let jasmineInterface;
|
||||
module.exports.noGlobals = function() {
|
||||
const { jasmineInterface } = bootWithoutGlobals(false);
|
||||
return jasmineInterface;
|
||||
};
|
||||
|
||||
return function bootWithoutGlobals() {
|
||||
if (!jasmineInterface) {
|
||||
const jasmine = jasmineRequire.core(jasmineRequire);
|
||||
const env = jasmine.getEnv({ suppressLoadErrors: true });
|
||||
jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
}
|
||||
const path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
return jasmineInterface;
|
||||
};
|
||||
}());
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
var rootPath = path.join(__dirname, "jasmine-core"),
|
||||
bootFiles = ['boot0.js', 'boot1.js'],
|
||||
legacyBootFiles = ['boot.js'],
|
||||
nodeBootFiles = ['node_boot.js'],
|
||||
cssFiles = [],
|
||||
jsFiles = [],
|
||||
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles, nodeBootFiles);
|
||||
const rootPath = path.join(__dirname, 'jasmine-core'),
|
||||
bootFiles = ['boot0.js', 'boot1.js'],
|
||||
legacyBootFiles = ['boot.js'],
|
||||
cssFiles = [],
|
||||
jsFiles = [],
|
||||
jsFilesToSkip = ['jasmine.js'].concat(bootFiles, legacyBootFiles);
|
||||
|
||||
fs.readdirSync(rootPath).forEach(function(file) {
|
||||
if(fs.statSync(path.join(rootPath, file)).isFile()) {
|
||||
switch(path.extname(file)) {
|
||||
if (fs.statSync(path.join(rootPath, file)).isFile()) {
|
||||
switch (path.extname(file)) {
|
||||
case '.css':
|
||||
cssFiles.push(file);
|
||||
break;
|
||||
break;
|
||||
case '.js':
|
||||
if (jsFilesToSkip.indexOf(file) < 0) {
|
||||
jsFiles.push(file);
|
||||
}
|
||||
break;
|
||||
jsFiles.push(file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports.files = {
|
||||
self: __filename,
|
||||
path: rootPath,
|
||||
bootDir: rootPath,
|
||||
bootFiles: bootFiles,
|
||||
nodeBootFiles: nodeBootFiles,
|
||||
cssFiles: cssFiles,
|
||||
jsFiles: ['jasmine.js'].concat(jsFiles),
|
||||
imagesDir: path.join(__dirname, '../images')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
Copyright (c) 2008-2019 Pivotal Labs
|
||||
Copyright (c) 2008-2025 The Jasmine developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -20,6 +21,7 @@ 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
|
||||
@@ -27,14 +29,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
source files or spec files are loaded.
|
||||
*/
|
||||
(function() {
|
||||
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
|
||||
const jasmineRequire = window.jasmineRequire || require('./jasmine.js');
|
||||
|
||||
/**
|
||||
* ## Require & 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),
|
||||
const jasmine = jasmineRequire.core(jasmineRequire),
|
||||
global = jasmine.getGlobal();
|
||||
global.jasmine = jasmine;
|
||||
|
||||
@@ -46,19 +48,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* Create the Jasmine environment. This is used to run all specs in a project.
|
||||
*/
|
||||
var env = jasmine.getEnv();
|
||||
const 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);
|
||||
const 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) {
|
||||
for (const property in jasmineInterface) {
|
||||
global[property] = jasmineInterface[property];
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
Copyright (c) 2008-2019 Pivotal Labs
|
||||
Copyright (c) 2008-2025 The Jasmine developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -20,6 +21,7 @@ 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
|
||||
@@ -34,23 +36,15 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var env = jasmine.getEnv();
|
||||
const 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({
|
||||
const queryString = new jasmine.QueryString({
|
||||
getWindowLocation: function() {
|
||||
return window.location;
|
||||
}
|
||||
});
|
||||
|
||||
var filterSpecs = !!queryString.getParam('spec');
|
||||
|
||||
var config = {
|
||||
const config = {
|
||||
stopOnSpecFailure: queryString.getParam('stopOnSpecFailure'),
|
||||
stopSpecOnExpectationFailure: queryString.getParam(
|
||||
'stopSpecOnExpectationFailure'
|
||||
@@ -58,13 +52,13 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
hideDisabled: queryString.getParam('hideDisabled')
|
||||
};
|
||||
|
||||
var random = queryString.getParam('random');
|
||||
const random = queryString.getParam('random');
|
||||
|
||||
if (random !== undefined && random !== '') {
|
||||
config.random = random;
|
||||
}
|
||||
|
||||
var seed = queryString.getParam('seed');
|
||||
const seed = queryString.getParam('seed');
|
||||
if (seed) {
|
||||
config.seed = seed;
|
||||
}
|
||||
@@ -73,7 +67,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
* ## 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({
|
||||
const htmlReporter = new jasmine.HtmlReporter({
|
||||
env: env,
|
||||
navigateWithNewParam: function(key, value) {
|
||||
return queryString.navigateWithNewParam(key, value);
|
||||
@@ -91,7 +85,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
return document.createTextNode.apply(document, arguments);
|
||||
},
|
||||
timer: new jasmine.Timer(),
|
||||
filterSpecs: filterSpecs
|
||||
queryString
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -103,14 +97,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
/**
|
||||
* 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');
|
||||
}
|
||||
});
|
||||
|
||||
const specFilter = new jasmine.HtmlExactSpecFilter({ queryString });
|
||||
config.specFilter = function(spec) {
|
||||
return specFilter.matches(spec.getFullName());
|
||||
return specFilter.matches(spec);
|
||||
};
|
||||
|
||||
env.configure(config);
|
||||
@@ -120,7 +109,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* 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;
|
||||
const currentWindowOnload = window.onload;
|
||||
|
||||
window.onload = function() {
|
||||
if (currentWindowOnload) {
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
function Player() {
|
||||
}
|
||||
Player.prototype.play = function(song) {
|
||||
this.currentlyPlayingSong = song;
|
||||
this.isPlaying = true;
|
||||
};
|
||||
|
||||
Player.prototype.pause = function() {
|
||||
this.isPlaying = false;
|
||||
};
|
||||
|
||||
Player.prototype.resume = function() {
|
||||
if (this.isPlaying) {
|
||||
throw new Error("song is already playing");
|
||||
class Player {
|
||||
play(song) {
|
||||
this.currentlyPlayingSong = song;
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
};
|
||||
pause() {
|
||||
this.isPlaying = false;
|
||||
}
|
||||
|
||||
Player.prototype.makeFavorite = function() {
|
||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||
};
|
||||
resume() {
|
||||
if (this.isPlaying) {
|
||||
throw new Error('song is already playing');
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
makeFavorite() {
|
||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Player;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
function Song() {
|
||||
class Song {
|
||||
persistFavoriteStatus(value) {
|
||||
// something complicated
|
||||
throw new Error('not yet implemented');
|
||||
}
|
||||
}
|
||||
|
||||
Song.prototype.persistFavoriteStatus = function(value) {
|
||||
// something complicated
|
||||
throw new Error("not yet implemented");
|
||||
};
|
||||
|
||||
module.exports = Song;
|
||||
|
||||
@@ -3,11 +3,11 @@ beforeEach(function () {
|
||||
toBePlaying: function () {
|
||||
return {
|
||||
compare: function (actual, expected) {
|
||||
var player = actual;
|
||||
const player = actual;
|
||||
|
||||
return {
|
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,36 +1,37 @@
|
||||
describe("Player", function() {
|
||||
var Player = require('../../lib/jasmine_examples/Player');
|
||||
var Song = require('../../lib/jasmine_examples/Song');
|
||||
var player;
|
||||
var song;
|
||||
const Player = require('../../lib/jasmine_examples/Player');
|
||||
const Song = require('../../lib/jasmine_examples/Song');
|
||||
|
||||
describe('Player', function() {
|
||||
let player;
|
||||
let song;
|
||||
|
||||
beforeEach(function() {
|
||||
player = new Player();
|
||||
song = new Song();
|
||||
});
|
||||
|
||||
it("should be able to play a Song", function() {
|
||||
it('should be able to play a Song', function() {
|
||||
player.play(song);
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
|
||||
//demonstrates use of custom matcher
|
||||
// demonstrates use of custom matcher
|
||||
expect(player).toBePlaying(song);
|
||||
});
|
||||
|
||||
describe("when song has been paused", function() {
|
||||
describe('when song has been paused', function() {
|
||||
beforeEach(function() {
|
||||
player.play(song);
|
||||
player.pause();
|
||||
});
|
||||
|
||||
it("should indicate that the song is currently paused", function() {
|
||||
it('should indicate that the song is currently paused', function() {
|
||||
expect(player.isPlaying).toBeFalsy();
|
||||
|
||||
// demonstrates use of 'not' with a custom matcher
|
||||
expect(player).not.toBePlaying(song);
|
||||
});
|
||||
|
||||
it("should be possible to resume", function() {
|
||||
it('should be possible to resume', function() {
|
||||
player.resume();
|
||||
expect(player.isPlaying).toBeTruthy();
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
@@ -38,7 +39,7 @@ describe("Player", function() {
|
||||
});
|
||||
|
||||
// demonstrates use of spies to intercept and test method calls
|
||||
it("tells the current song if the user has made it a favorite", function() {
|
||||
it('tells the current song if the user has made it a favorite', function() {
|
||||
spyOn(song, 'persistFavoriteStatus');
|
||||
|
||||
player.play(song);
|
||||
@@ -48,13 +49,13 @@ describe("Player", function() {
|
||||
});
|
||||
|
||||
//demonstrates use of expected exceptions
|
||||
describe("#resume", function() {
|
||||
it("should throw an exception if song is already playing", function() {
|
||||
describe('#resume', function() {
|
||||
it('should throw an exception if song is already playing', function() {
|
||||
player.play(song);
|
||||
|
||||
expect(function() {
|
||||
player.resume();
|
||||
}).toThrowError("song is already playing");
|
||||
}).toThrowError('song is already playing');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
describe("Player", function() {
|
||||
var player;
|
||||
var song;
|
||||
describe('Player', function() {
|
||||
let player;
|
||||
let song;
|
||||
|
||||
beforeEach(function() {
|
||||
player = new Player();
|
||||
song = new Song();
|
||||
});
|
||||
|
||||
it("should be able to play a Song", function() {
|
||||
it('should be able to play a Song', function() {
|
||||
player.play(song);
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
|
||||
//demonstrates use of custom matcher
|
||||
// demonstrates use of custom matcher
|
||||
expect(player).toBePlaying(song);
|
||||
});
|
||||
|
||||
describe("when song has been paused", function() {
|
||||
describe('when song has been paused', function() {
|
||||
beforeEach(function() {
|
||||
player.play(song);
|
||||
player.pause();
|
||||
});
|
||||
|
||||
it("should indicate that the song is currently paused", function() {
|
||||
it('should indicate that the song is currently paused', function() {
|
||||
expect(player.isPlaying).toBeFalsy();
|
||||
|
||||
// demonstrates use of 'not' with a custom matcher
|
||||
expect(player).not.toBePlaying(song);
|
||||
});
|
||||
|
||||
it("should be possible to resume", function() {
|
||||
it('should be possible to resume', function() {
|
||||
player.resume();
|
||||
expect(player.isPlaying).toBeTruthy();
|
||||
expect(player.currentlyPlayingSong).toEqual(song);
|
||||
@@ -36,7 +36,7 @@ describe("Player", function() {
|
||||
});
|
||||
|
||||
// demonstrates use of spies to intercept and test method calls
|
||||
it("tells the current song if the user has made it a favorite", function() {
|
||||
it('tells the current song if the user has made it a favorite', function() {
|
||||
spyOn(song, 'persistFavoriteStatus');
|
||||
|
||||
player.play(song);
|
||||
@@ -46,13 +46,13 @@ describe("Player", function() {
|
||||
});
|
||||
|
||||
//demonstrates use of expected exceptions
|
||||
describe("#resume", function() {
|
||||
it("should throw an exception if song is already playing", function() {
|
||||
describe('#resume', function() {
|
||||
it('should throw an exception if song is already playing', function() {
|
||||
player.play(song);
|
||||
|
||||
expect(function() {
|
||||
player.resume();
|
||||
}).toThrowError("song is already playing");
|
||||
}).toThrowError('song is already playing');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ beforeEach(function () {
|
||||
toBePlaying: function () {
|
||||
return {
|
||||
compare: function (actual, expected) {
|
||||
var player = actual;
|
||||
const player = actual;
|
||||
|
||||
return {
|
||||
pass: player.currentlyPlayingSong === expected && player.isPlaying
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
function Player() {
|
||||
}
|
||||
Player.prototype.play = function(song) {
|
||||
this.currentlyPlayingSong = song;
|
||||
this.isPlaying = true;
|
||||
};
|
||||
|
||||
Player.prototype.pause = function() {
|
||||
this.isPlaying = false;
|
||||
};
|
||||
|
||||
Player.prototype.resume = function() {
|
||||
if (this.isPlaying) {
|
||||
throw new Error("song is already playing");
|
||||
class Player {
|
||||
play(song) {
|
||||
this.currentlyPlayingSong = song;
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
};
|
||||
pause() {
|
||||
this.isPlaying = false;
|
||||
}
|
||||
|
||||
Player.prototype.makeFavorite = function() {
|
||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||
};
|
||||
resume() {
|
||||
if (this.isPlaying) {
|
||||
throw new Error('song is already playing');
|
||||
}
|
||||
|
||||
this.isPlaying = true;
|
||||
}
|
||||
|
||||
makeFavorite() {
|
||||
this.currentlyPlayingSong.persistFavoriteStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
function Song() {
|
||||
class Song {
|
||||
persistFavoriteStatus(value) {
|
||||
// something complicated
|
||||
throw new Error('not yet implemented');
|
||||
}
|
||||
}
|
||||
|
||||
Song.prototype.persistFavoriteStatus = function(value) {
|
||||
// something complicated
|
||||
throw new Error("not yet implemented");
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 Pivotal Labs
|
||||
Copyright (c) 2008-2019 Pivotal Labs
|
||||
Copyright (c) 2008-2025 The Jasmine developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@@ -20,27 +21,32 @@ 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
var jasmineRequire = window.jasmineRequire || require('./jasmine.js');
|
||||
|
||||
jasmineRequire.html = function(j$) {
|
||||
j$.ResultsNode = jasmineRequire.ResultsNode();
|
||||
j$.private.ResultsNode = jasmineRequire.ResultsNode();
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.QueryString = jasmineRequire.QueryString();
|
||||
j$.HtmlSpecFilter = jasmineRequire.HtmlSpecFilter();
|
||||
j$.HtmlExactSpecFilter = jasmineRequire.HtmlExactSpecFilter();
|
||||
};
|
||||
|
||||
jasmineRequire.HtmlReporter = function(j$) {
|
||||
function ResultsStateBuilder() {
|
||||
this.topResults = new j$.ResultsNode({}, '', null);
|
||||
this.topResults = new j$.private.ResultsNode({}, '', null);
|
||||
this.currentParent = this.topResults;
|
||||
this.specsExecuted = 0;
|
||||
this.failureCount = 0;
|
||||
this.pendingSpecCount = 0;
|
||||
this.suitesById = [];
|
||||
}
|
||||
|
||||
ResultsStateBuilder.prototype.suiteStarted = function(result) {
|
||||
this.currentParent.addChild(result, 'suite');
|
||||
this.currentParent = this.currentParent.last();
|
||||
this.suitesById[result.id] = this.currentParent;
|
||||
};
|
||||
|
||||
ResultsStateBuilder.prototype.suiteDone = function(result) {
|
||||
@@ -78,21 +84,39 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @class HtmlReporter
|
||||
* @classdesc Displays results and allows re-running individual specs and suites.
|
||||
* @implements {Reporter}
|
||||
* @param options Options object. See lib/jasmine-core/boot1.js for details.
|
||||
* @since 1.2.0
|
||||
*/
|
||||
function HtmlReporter(options) {
|
||||
var config = function() {
|
||||
return (options.env && options.env.configuration()) || {};
|
||||
},
|
||||
getContainer = options.getContainer,
|
||||
createElement = options.createElement,
|
||||
createTextNode = options.createTextNode,
|
||||
navigateWithNewParam = options.navigateWithNewParam || function() {},
|
||||
addToExistingQueryString =
|
||||
options.addToExistingQueryString || defaultQueryString,
|
||||
filterSpecs = options.filterSpecs,
|
||||
htmlReporterMain,
|
||||
symbols,
|
||||
deprecationWarnings = [];
|
||||
function config() {
|
||||
return (options.env && options.env.configuration()) || {};
|
||||
}
|
||||
|
||||
const getContainer = options.getContainer;
|
||||
const createElement = options.createElement;
|
||||
const createTextNode = options.createTextNode;
|
||||
// TODO: in the next major release, replace navigateWithNewParam and
|
||||
// addToExistingQueryString with direct usage of options.queryString
|
||||
const navigateWithNewParam = options.navigateWithNewParam || function() {};
|
||||
const addToExistingQueryString =
|
||||
options.addToExistingQueryString || defaultQueryString;
|
||||
const filterSpecs = options.queryString
|
||||
? !!options.queryString.getParam('spec')
|
||||
: options.filterSpecs; // For compatibility with pre-5.11 boot files
|
||||
let htmlReporterMain;
|
||||
let symbols;
|
||||
const deprecationWarnings = [];
|
||||
const failures = [];
|
||||
|
||||
/**
|
||||
* Initializes the reporter. Should be called before {@link Env#execute}.
|
||||
* @function
|
||||
* @name HtmlReporter#initialize
|
||||
*/
|
||||
this.initialize = function() {
|
||||
clearPrior();
|
||||
htmlReporterMain = createDom(
|
||||
@@ -119,14 +143,14 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
getContainer().appendChild(htmlReporterMain);
|
||||
};
|
||||
|
||||
var totalSpecsDefined;
|
||||
let totalSpecsDefined;
|
||||
this.jasmineStarted = function(options) {
|
||||
totalSpecsDefined = options.totalSpecsDefined || 0;
|
||||
};
|
||||
|
||||
var summary = createDom('div', { className: 'jasmine-summary' });
|
||||
const summary = createDom('div', { className: 'jasmine-summary' });
|
||||
|
||||
var stateBuilder = new ResultsStateBuilder();
|
||||
const stateBuilder = new ResultsStateBuilder();
|
||||
|
||||
this.suiteStarted = function(result) {
|
||||
stateBuilder.suiteStarted(result);
|
||||
@@ -145,15 +169,16 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
stateBuilder.specStarted(result);
|
||||
};
|
||||
|
||||
var failures = [];
|
||||
this.specDone = function(result) {
|
||||
stateBuilder.specDone(result);
|
||||
|
||||
if (noExpectations(result)) {
|
||||
var noSpecMsg = "Spec '" + result.fullName + "' has no expectations.";
|
||||
const noSpecMsg = "Spec '" + result.fullName + "' has no expectations.";
|
||||
if (result.status === 'failed') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(noSpecMsg);
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(noSpecMsg);
|
||||
}
|
||||
}
|
||||
@@ -194,10 +219,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
this.jasmineDone = function(doneResult) {
|
||||
stateBuilder.jasmineDone(doneResult);
|
||||
var banner = find('.jasmine-banner');
|
||||
var alert = find('.jasmine-alert');
|
||||
var order = doneResult && doneResult.order;
|
||||
var i;
|
||||
const banner = find('.jasmine-banner');
|
||||
const alert = find('.jasmine-alert');
|
||||
const order = doneResult && doneResult.order;
|
||||
|
||||
alert.appendChild(
|
||||
createDom(
|
||||
'span',
|
||||
@@ -209,14 +234,14 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
banner.appendChild(optionsMenu(config()));
|
||||
|
||||
if (stateBuilder.specsExecuted < totalSpecsDefined) {
|
||||
var skippedMessage =
|
||||
const 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 =
|
||||
const skippedLink =
|
||||
(window.location.pathname || '') +
|
||||
addToExistingQueryString('spec', '');
|
||||
alert.appendChild(
|
||||
@@ -231,10 +256,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
)
|
||||
);
|
||||
}
|
||||
var statusBarMessage = '';
|
||||
var statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
var globalFailures = (doneResult && doneResult.failedExpectations) || [];
|
||||
var failed = stateBuilder.failureCount + globalFailures.length > 0;
|
||||
let statusBarMessage = '';
|
||||
let statusBarClassName = 'jasmine-overall-result jasmine-bar ';
|
||||
const globalFailures =
|
||||
(doneResult && doneResult.failedExpectations) || [];
|
||||
const failed = stateBuilder.failureCount + globalFailures.length > 0;
|
||||
|
||||
if (totalSpecsDefined > 0 || failed) {
|
||||
statusBarMessage +=
|
||||
@@ -260,7 +286,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
statusBarClassName += ' jasmine-failed ';
|
||||
}
|
||||
|
||||
var seedBar;
|
||||
let seedBar;
|
||||
if (order && order.random) {
|
||||
seedBar = createDom(
|
||||
'span',
|
||||
@@ -286,10 +312,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
)
|
||||
);
|
||||
|
||||
var errorBarClassName = 'jasmine-bar jasmine-errored';
|
||||
var afterAllMessagePrefix = 'AfterAll ';
|
||||
const errorBarClassName = 'jasmine-bar jasmine-errored';
|
||||
const afterAllMessagePrefix = 'AfterAll ';
|
||||
|
||||
for (i = 0; i < globalFailures.length; i++) {
|
||||
for (let i = 0; i < globalFailures.length; i++) {
|
||||
alert.appendChild(
|
||||
createDom(
|
||||
'span',
|
||||
@@ -301,7 +327,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
function globalFailureMessage(failure) {
|
||||
if (failure.globalErrorType === 'load') {
|
||||
var prefix = 'Error during loading: ' + failure.message;
|
||||
const prefix = 'Error during loading: ' + failure.message;
|
||||
|
||||
if (failure.filename) {
|
||||
return (
|
||||
@@ -319,9 +345,9 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
addDeprecationWarnings(doneResult);
|
||||
|
||||
for (i = 0; i < deprecationWarnings.length; i++) {
|
||||
var children = [],
|
||||
context;
|
||||
for (let i = 0; i < deprecationWarnings.length; i++) {
|
||||
const children = [];
|
||||
let context;
|
||||
|
||||
switch (deprecationWarnings[i].runnableType) {
|
||||
case 'spec':
|
||||
@@ -355,7 +381,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
}
|
||||
|
||||
var results = find('.jasmine-results');
|
||||
const results = find('.jasmine-results');
|
||||
results.appendChild(summary);
|
||||
|
||||
summaryList(stateBuilder.topResults, summary);
|
||||
@@ -397,8 +423,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
|
||||
setMenuModeTo('jasmine-failure-list');
|
||||
|
||||
var failureNode = find('.jasmine-failures');
|
||||
for (i = 0; i < failures.length; i++) {
|
||||
const failureNode = find('.jasmine-failures');
|
||||
for (let i = 0; i < failures.length; i++) {
|
||||
failureNode.appendChild(failures[i]);
|
||||
}
|
||||
}
|
||||
@@ -407,16 +433,16 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
return this;
|
||||
|
||||
function failureDom(result) {
|
||||
var failure = createDom(
|
||||
const failure = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-spec-detail jasmine-failed' },
|
||||
failureDescription(result, stateBuilder.currentParent),
|
||||
createDom('div', { className: 'jasmine-messages' })
|
||||
);
|
||||
var messages = failure.childNodes[1];
|
||||
const messages = failure.childNodes[1];
|
||||
|
||||
for (var i = 0; i < result.failedExpectations.length; i++) {
|
||||
var expectation = result.failedExpectations[i];
|
||||
for (let i = 0; i < result.failedExpectations.length; i++) {
|
||||
const expectation = result.failedExpectations[i];
|
||||
messages.appendChild(
|
||||
createDom(
|
||||
'div',
|
||||
@@ -451,7 +477,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function debugLogTable(debugLogs) {
|
||||
var tbody = createDom('tbody');
|
||||
const tbody = createDom('tbody');
|
||||
|
||||
debugLogs.forEach(function(entry) {
|
||||
tbody.appendChild(
|
||||
@@ -459,7 +485,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
'tr',
|
||||
{},
|
||||
createDom('td', {}, entry.timestamp.toString()),
|
||||
createDom('td', {}, entry.message)
|
||||
createDom(
|
||||
'td',
|
||||
{ className: 'jasmine-debug-log-msg' },
|
||||
entry.message
|
||||
)
|
||||
)
|
||||
);
|
||||
});
|
||||
@@ -491,14 +521,14 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function summaryList(resultsTree, domParent) {
|
||||
var specListNode;
|
||||
for (var i = 0; i < resultsTree.children.length; i++) {
|
||||
var resultNode = resultsTree.children[i];
|
||||
let specListNode;
|
||||
for (let i = 0; i < resultsTree.children.length; i++) {
|
||||
const resultNode = resultsTree.children[i];
|
||||
if (filterSpecs && !hasActiveSpec(resultNode)) {
|
||||
continue;
|
||||
}
|
||||
if (resultNode.type === 'suite') {
|
||||
var suiteListNode = createDom(
|
||||
const suiteListNode = createDom(
|
||||
'ul',
|
||||
{ className: 'jasmine-suite', id: 'suite-' + resultNode.result.id },
|
||||
createDom(
|
||||
@@ -523,18 +553,17 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
specListNode = createDom('ul', { className: 'jasmine-specs' });
|
||||
domParent.appendChild(specListNode);
|
||||
}
|
||||
var specDescription = resultNode.result.description;
|
||||
let 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;
|
||||
if (resultNode.result.status === 'pending') {
|
||||
if (resultNode.result.pendingReason !== '') {
|
||||
specDescription +=
|
||||
' PENDING WITH MESSAGE: ' + resultNode.result.pendingReason;
|
||||
} else {
|
||||
specDescription += ' PENDING';
|
||||
}
|
||||
}
|
||||
specListNode.appendChild(
|
||||
createDom(
|
||||
@@ -547,6 +576,11 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
'a',
|
||||
{ href: specHref(resultNode.result) },
|
||||
specDescription
|
||||
),
|
||||
createDom(
|
||||
'span',
|
||||
{ className: 'jasmine-spec-duration' },
|
||||
'(' + resultNode.result.duration + 'ms)'
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -555,7 +589,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function optionsMenu(config) {
|
||||
var optionsMenuDom = createDom(
|
||||
const optionsMenuDom = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-run-options' },
|
||||
createDom('span', { className: 'jasmine-trigger' }, 'Options'),
|
||||
@@ -621,13 +655,15 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
)
|
||||
);
|
||||
|
||||
var failFastCheckbox = optionsMenuDom.querySelector('#jasmine-fail-fast');
|
||||
const failFastCheckbox = optionsMenuDom.querySelector(
|
||||
'#jasmine-fail-fast'
|
||||
);
|
||||
failFastCheckbox.checked = config.stopOnSpecFailure;
|
||||
failFastCheckbox.onclick = function() {
|
||||
navigateWithNewParam('stopOnSpecFailure', !config.stopOnSpecFailure);
|
||||
};
|
||||
|
||||
var throwCheckbox = optionsMenuDom.querySelector(
|
||||
const throwCheckbox = optionsMenuDom.querySelector(
|
||||
'#jasmine-throw-failures'
|
||||
);
|
||||
throwCheckbox.checked = config.stopSpecOnExpectationFailure;
|
||||
@@ -638,7 +674,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
);
|
||||
};
|
||||
|
||||
var randomCheckbox = optionsMenuDom.querySelector(
|
||||
const randomCheckbox = optionsMenuDom.querySelector(
|
||||
'#jasmine-random-order'
|
||||
);
|
||||
randomCheckbox.checked = config.random;
|
||||
@@ -646,13 +682,15 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
navigateWithNewParam('random', !config.random);
|
||||
};
|
||||
|
||||
var hideDisabled = optionsMenuDom.querySelector('#jasmine-hide-disabled');
|
||||
const hideDisabled = optionsMenuDom.querySelector(
|
||||
'#jasmine-hide-disabled'
|
||||
);
|
||||
hideDisabled.checked = config.hideDisabled;
|
||||
hideDisabled.onclick = function() {
|
||||
navigateWithNewParam('hideDisabled', !config.hideDisabled);
|
||||
};
|
||||
|
||||
var optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
|
||||
const optionsTrigger = optionsMenuDom.querySelector('.jasmine-trigger'),
|
||||
optionsPayload = optionsMenuDom.querySelector('.jasmine-payload'),
|
||||
isOpen = /\bjasmine-open\b/;
|
||||
|
||||
@@ -671,7 +709,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function failureDescription(result, suite) {
|
||||
var wrapper = createDom(
|
||||
const wrapper = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-description' },
|
||||
createDom(
|
||||
@@ -680,7 +718,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
result.description
|
||||
)
|
||||
);
|
||||
var suiteLink;
|
||||
let suiteLink;
|
||||
|
||||
while (suite && suite.parent) {
|
||||
wrapper.insertBefore(createTextNode(' > '), wrapper.firstChild);
|
||||
@@ -697,25 +735,10 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
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;
|
||||
for (let i = 0; i < result.deprecationWarnings.length; i++) {
|
||||
const warning = result.deprecationWarnings[i].message;
|
||||
deprecationWarnings.push({
|
||||
message: warning,
|
||||
stack: result.deprecationWarnings[i].stack,
|
||||
@@ -727,8 +750,8 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function createExpander(stackTrace) {
|
||||
var expandLink = createDom('a', { href: '#' }, 'Show stack trace');
|
||||
var root = createDom(
|
||||
const expandLink = createDom('a', { href: '#' }, 'Show stack trace');
|
||||
const root = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-expander' },
|
||||
expandLink,
|
||||
@@ -759,8 +782,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function clearPrior() {
|
||||
// return the reporter
|
||||
var oldReporter = find('');
|
||||
const oldReporter = find('');
|
||||
|
||||
if (oldReporter) {
|
||||
getContainer().removeChild(oldReporter);
|
||||
@@ -768,22 +790,21 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function createDom(type, attrs, childrenArrayOrVarArgs) {
|
||||
var el = createElement(type),
|
||||
children,
|
||||
i;
|
||||
const el = createElement(type);
|
||||
let children;
|
||||
|
||||
if (j$.isArray_(childrenArrayOrVarArgs)) {
|
||||
if (j$.private.isArray(childrenArrayOrVarArgs)) {
|
||||
children = childrenArrayOrVarArgs;
|
||||
} else {
|
||||
children = [];
|
||||
|
||||
for (i = 2; i < arguments.length; i++) {
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
children.push(arguments[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < children.length; i++) {
|
||||
var child = children[i];
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(createTextNode(child));
|
||||
@@ -794,7 +815,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
for (const attr in attrs) {
|
||||
if (attr == 'className') {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
@@ -806,16 +827,38 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function pluralize(singular, count) {
|
||||
var word = count == 1 ? singular : singular + 's';
|
||||
const word = count == 1 ? singular : singular + 's';
|
||||
|
||||
return '' + count + ' ' + word;
|
||||
}
|
||||
|
||||
function suitePath(suite) {
|
||||
const els = [];
|
||||
|
||||
while (suite && suite.parent) {
|
||||
els.unshift(suite.result.description);
|
||||
suite = suite.parent;
|
||||
}
|
||||
|
||||
return els;
|
||||
}
|
||||
|
||||
function suiteHref(suite) {
|
||||
return pathHref(suitePath(suite));
|
||||
}
|
||||
|
||||
function specHref(result) {
|
||||
const suite = stateBuilder.suitesById[result.parentSuiteId];
|
||||
const path = suitePath(suite);
|
||||
path.push(result.description);
|
||||
return pathHref(path);
|
||||
}
|
||||
|
||||
function pathHref(path) {
|
||||
// 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)
|
||||
addToExistingQueryString('spec', JSON.stringify(path))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -836,7 +879,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
function noExpectations(result) {
|
||||
var allExpectations =
|
||||
const allExpectations =
|
||||
result.failedExpectations.length + result.passedExpectations.length;
|
||||
|
||||
return (
|
||||
@@ -851,7 +894,7 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
}
|
||||
|
||||
if (resultNode.type == 'suite') {
|
||||
for (var i = 0, j = resultNode.children.length; i < j; i++) {
|
||||
for (let i = 0, j = resultNode.children.length; i < j; i++) {
|
||||
if (hasActiveSpec(resultNode.children[i])) {
|
||||
return true;
|
||||
}
|
||||
@@ -864,13 +907,36 @@ jasmineRequire.HtmlReporter = function(j$) {
|
||||
};
|
||||
|
||||
jasmineRequire.HtmlSpecFilter = function() {
|
||||
/**
|
||||
* @name HtmlSpecFilter
|
||||
* @classdesc Legacy HTML spec filter, for backward compatibility
|
||||
* with boot files that predate {@link HtmlExactSpecFilter}.
|
||||
* @param options Object with a filterString method
|
||||
* @constructor
|
||||
* @deprecated
|
||||
* @since 1.2.0
|
||||
*/
|
||||
// Legacy HTML spec filter, preserved for backward compatibility with
|
||||
// boot files that predate HtmlExactSpecFilterV2
|
||||
function HtmlSpecFilter(options) {
|
||||
var filterString =
|
||||
options &&
|
||||
options.filterString() &&
|
||||
options.filterString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
var filterPattern = new RegExp(filterString);
|
||||
let filterString = (options && options.filterString()) || '';
|
||||
|
||||
if (filterString.startsWith('[')) {
|
||||
// Convert an HtmlExactSpecFilterV2 string into something we can use
|
||||
filterString = JSON.parse(filterString).join(' ');
|
||||
}
|
||||
|
||||
filterString = filterString.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||
|
||||
const filterPattern = new RegExp(filterString);
|
||||
|
||||
/**
|
||||
* Determines whether the spec with the specified name should be executed.
|
||||
* @name HtmlSpecFilter#matches
|
||||
* @function
|
||||
* @param {string} specName The full name of the spec
|
||||
* @returns {boolean}
|
||||
*/
|
||||
this.matches = function(specName) {
|
||||
return filterPattern.test(specName);
|
||||
};
|
||||
@@ -904,46 +970,65 @@ jasmineRequire.ResultsNode = function() {
|
||||
};
|
||||
|
||||
jasmineRequire.QueryString = function() {
|
||||
function QueryString(options) {
|
||||
this.navigateWithNewParam = function(key, value) {
|
||||
options.getWindowLocation().search = this.fullStringWithNewParam(
|
||||
/**
|
||||
* Reads and manipulates the query string.
|
||||
* @since 2.0.0
|
||||
*/
|
||||
class QueryString {
|
||||
#getWindowLocation;
|
||||
|
||||
/**
|
||||
* @param options Object with a getWindowLocation property, which should be
|
||||
* a function returning the current value of window.location.
|
||||
*/
|
||||
constructor(options) {
|
||||
this.#getWindowLocation = options.getWindowLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified query parameter and navigates to the resulting URL.
|
||||
* @param {string} key
|
||||
* @param {string} value
|
||||
*/
|
||||
navigateWithNewParam(key, value) {
|
||||
this.#getWindowLocation().search = this.fullStringWithNewParam(
|
||||
key,
|
||||
value
|
||||
);
|
||||
};
|
||||
|
||||
this.fullStringWithNewParam = function(key, value) {
|
||||
var paramMap = queryStringToParamMap();
|
||||
paramMap[key] = value;
|
||||
return toQueryString(paramMap);
|
||||
};
|
||||
|
||||
this.getParam = function(key) {
|
||||
return queryStringToParamMap()[key];
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function toQueryString(paramMap) {
|
||||
var qStrPairs = [];
|
||||
for (var prop in paramMap) {
|
||||
qStrPairs.push(
|
||||
encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])
|
||||
);
|
||||
}
|
||||
return '?' + qStrPairs.join('&');
|
||||
}
|
||||
|
||||
function queryStringToParamMap() {
|
||||
var paramStr = options.getWindowLocation().search.substring(1),
|
||||
params = [],
|
||||
paramMap = {};
|
||||
/**
|
||||
* Returns a new URL based on the current location, with the specified
|
||||
* query parameter set.
|
||||
* @param {string} key
|
||||
* @param {string} value
|
||||
* @return {string}
|
||||
*/
|
||||
fullStringWithNewParam(key, value) {
|
||||
const paramMap = this.#queryStringToParamMap();
|
||||
paramMap[key] = value;
|
||||
return toQueryString(paramMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the specified query parameter.
|
||||
* @param {string} key
|
||||
* @return {string}
|
||||
*/
|
||||
getParam(key) {
|
||||
return this.#queryStringToParamMap()[key];
|
||||
}
|
||||
|
||||
#queryStringToParamMap() {
|
||||
const paramStr = this.#getWindowLocation().search.substring(1);
|
||||
let params = [];
|
||||
const paramMap = {};
|
||||
|
||||
if (paramStr.length > 0) {
|
||||
params = paramStr.split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
var value = decodeURIComponent(p[1]);
|
||||
for (let i = 0; i < params.length; i++) {
|
||||
const p = params[i].split('=');
|
||||
let value = decodeURIComponent(p[1]);
|
||||
if (value === 'true' || value === 'false') {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
@@ -955,5 +1040,68 @@ jasmineRequire.QueryString = function() {
|
||||
}
|
||||
}
|
||||
|
||||
function toQueryString(paramMap) {
|
||||
const qStrPairs = [];
|
||||
for (const prop in paramMap) {
|
||||
qStrPairs.push(
|
||||
encodeURIComponent(prop) + '=' + encodeURIComponent(paramMap[prop])
|
||||
);
|
||||
}
|
||||
return '?' + qStrPairs.join('&');
|
||||
}
|
||||
|
||||
return QueryString;
|
||||
};
|
||||
|
||||
jasmineRequire.HtmlExactSpecFilter = function() {
|
||||
/**
|
||||
* Spec filter for use with {@link HtmlReporter}
|
||||
*
|
||||
* See lib/jasmine-core/boot1.js for usage.
|
||||
* @since 5.11.0
|
||||
*/
|
||||
class HtmlExactSpecFilter {
|
||||
#getFilterString;
|
||||
|
||||
/**
|
||||
* Create a filter instance.
|
||||
* @param options Object with a queryString property, which should be an
|
||||
* instance of {@link QueryString}.
|
||||
*/
|
||||
constructor(options) {
|
||||
this.#getFilterString = function() {
|
||||
return options.queryString.getParam('spec');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the specified spec should be executed.
|
||||
* @param {Spec} spec
|
||||
* @returns {boolean}
|
||||
*/
|
||||
matches(spec) {
|
||||
const filterString = this.#getFilterString();
|
||||
|
||||
if (!filterString) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const filterPath = JSON.parse(this.#getFilterString());
|
||||
const specPath = spec.getPath();
|
||||
|
||||
if (filterPath.length > specPath.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < filterPath.length; i++) {
|
||||
if (specPath[i] !== filterPath[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return HtmlExactSpecFilter;
|
||||
};
|
||||
|
||||
@@ -55,9 +55,6 @@ body {
|
||||
position: fixed;
|
||||
right: 100%;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-version {
|
||||
color: #aaa;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-banner {
|
||||
margin-top: 14px;
|
||||
}
|
||||
@@ -169,10 +166,11 @@ body {
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-menu {
|
||||
background-color: #fff;
|
||||
color: #aaa;
|
||||
color: #000;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-bar.jasmine-menu a {
|
||||
color: #333;
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-bar a {
|
||||
color: white;
|
||||
@@ -231,6 +229,9 @@ body {
|
||||
.jasmine_html-reporter .jasmine-specs li.jasmine-excluded a:before {
|
||||
content: "• ";
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-specs li .jasmine-spec-duration {
|
||||
margin-left: 1em;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-description + .jasmine-suite {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -297,4 +298,7 @@ body {
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-debug-log table, .jasmine_html-reporter .jasmine-debug-log th, .jasmine_html-reporter .jasmine-debug-log td {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-debug-log .jasmine-debug-log-msg {
|
||||
white-space: pre;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2008-2022 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.
|
||||
*/
|
||||
module.exports = function(jasmineRequire) {
|
||||
var jasmine = jasmineRequire.core(jasmineRequire);
|
||||
|
||||
var env = jasmine.getEnv({ suppressLoadErrors: true });
|
||||
|
||||
var jasmineInterface = jasmineRequire.interface(jasmine, env);
|
||||
|
||||
extend(global, jasmineInterface);
|
||||
|
||||
function extend(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
}
|
||||
|
||||
return jasmine;
|
||||
};
|
||||
90
package.json
90
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "jasmine-core",
|
||||
"license": "MIT",
|
||||
"version": "4.1.1",
|
||||
"version": "6.0.0-alpha.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jasmine/jasmine.git"
|
||||
@@ -15,9 +15,11 @@
|
||||
],
|
||||
"scripts": {
|
||||
"posttest": "eslint \"src/**/*.js\" \"spec/**/*.js\" && prettier --check \"src/**/*.js\" \"spec/**/*.js\"",
|
||||
"test": "grunt --stack execSpecsInNode",
|
||||
"test": "node scripts/runSpecsInNode.js",
|
||||
"test:parallel": "node scripts/runSpecsInParallel.js",
|
||||
"cleanup": "prettier --write \"src/**/*.js\" \"spec/**/*.js\"",
|
||||
"build": "grunt buildDistribution",
|
||||
"build": "node scripts/buildDistribution.js",
|
||||
"buildStandaloneDist": "node scripts/buildStandaloneDist.js",
|
||||
"serve": "node spec/support/localJasmineBrowser.js",
|
||||
"serve:performance": "node spec/support/localJasmineBrowser.js jasmine-browser-performance.json",
|
||||
"ci": "node spec/support/ci.js",
|
||||
@@ -27,82 +29,32 @@
|
||||
"homepage": "https://jasmine.github.io",
|
||||
"main": "./lib/jasmine-core.js",
|
||||
"files": [
|
||||
"MIT.LICENSE",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"images/*.{png,svg}",
|
||||
"lib/**/*.{js,css}",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-compat": "^4.0.0",
|
||||
"glob": "^7.2.0",
|
||||
"grunt": "^1.0.4",
|
||||
"grunt-cli": "^1.3.2",
|
||||
"grunt-contrib-compress": "^2.0.0",
|
||||
"grunt-contrib-concat": "^2.0.0",
|
||||
"grunt-css-url-embed": "^1.11.1",
|
||||
"grunt-sass": "^3.0.2",
|
||||
"jasmine": "github:jasmine/jasmine-npm#main",
|
||||
"jasmine-browser-runner": "github:jasmine/jasmine-browser#main",
|
||||
"jsdom": "^19.0.0",
|
||||
"load-grunt-tasks": "^5.1.0",
|
||||
"@eslint/eslintrc": "^3.3.1",
|
||||
"@eslint/js": "^9.24.0",
|
||||
"archiver": "^7.0.1",
|
||||
"css-url-embed": "^0.1.0",
|
||||
"ejs": "^3.1.10",
|
||||
"eslint": "^9.24.0",
|
||||
"eslint-plugin-compat": "^6.0.2",
|
||||
"glob": "^10.2.3",
|
||||
"globals": "^16.0.0",
|
||||
"jasmine": "^5.0.0",
|
||||
"jasmine-browser-runner": "github:jasmine/jasmine-browser-runner#4.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"prettier": "1.17.1",
|
||||
"sass": "^1.45.1",
|
||||
"shelljs": "^0.8.3",
|
||||
"temp": "^0.9.0"
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"plugin:compat/recommended"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es2017": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"rules": {
|
||||
"quotes": [
|
||||
"error",
|
||||
"single",
|
||||
{
|
||||
"avoidEscape": true
|
||||
}
|
||||
],
|
||||
"no-unused-vars": [
|
||||
"error",
|
||||
{
|
||||
"args": "none"
|
||||
}
|
||||
],
|
||||
"no-implicit-globals": "error",
|
||||
"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"
|
||||
}
|
||||
"sass": "^1.58.3"
|
||||
},
|
||||
"browserslist": [
|
||||
"Safari >= 13",
|
||||
"Safari >= 16",
|
||||
"Firefox >= 102",
|
||||
"last 2 Chrome versions",
|
||||
"last 2 Firefox versions",
|
||||
"Firefox >= 68",
|
||||
"last 2 Edge versions"
|
||||
]
|
||||
}
|
||||
|
||||
41
release_notes/4.2.0.md
Normal file
41
release_notes/4.2.0.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Jasmine 4.2.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Added a jasmine.is asymmetric equality tester
|
||||
* Allows the use of === comparisons for specific fields of an object that
|
||||
should otherwise be compared with the default deep value equality logic.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* More reliably report errors that occur late in the suite/spec lifecycle
|
||||
* Previously, an error that occurred after Jasmine started to report the
|
||||
suiteDone or specDone event for the current runable would not be reliably
|
||||
reported. Now such an error is reported on the nearest ancestor suite whose
|
||||
suiteDone event has not yet been reported.
|
||||
|
||||
* Don't report a deprecation when a runnable uses two forms of async
|
||||
* This was made into an error in 4.0, so the deprecation is redundant.
|
||||
|
||||
* Include property getter values in pretty-printed objects
|
||||
|
||||
## Documentation Updates
|
||||
|
||||
* Removed duplicate Suite and Spec jsdocs
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.2.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-15 |
|
||||
| Chrome | 102 |
|
||||
| Firefox | 91, 101 |
|
||||
| Edge | 101 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
40
release_notes/4.3.0.md
Normal file
40
release_notes/4.3.0.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Jasmine 4.3.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Added [`jasmine.spyOnGlobalErrorsAsync`](https://jasmine.github.io/api/4.3/jasmine.html#.spyOnGlobalErrorsAsync),
|
||||
to better support testing code that's
|
||||
expected to produce unhandled exceptions or unhandled promise rejections
|
||||
* Fixes [#1843](https://github.com/jasmine/jasmine/issues/1843)
|
||||
* Fixes [#1453](https://github.com/jasmine/jasmine/issues/1453)
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Updated the README to reduce redundancy and update support links
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Split `Env` into several smaller classes
|
||||
* Replaced uses of `var` with `const`/`let`
|
||||
* Replaced most uses of `self = this` with arrow fns
|
||||
* Removed obsolete and unused utility fns
|
||||
* Separated reporter- and runable-specific queue runner configuration
|
||||
* Added more test coverage for default spy strategies
|
||||
* Converted integration specs to `async`/`await`
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.3.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-15 |
|
||||
| Chrome | 103 |
|
||||
| Firefox | 91, 102 |
|
||||
| Edge | 103 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
28
release_notes/4.4.0.md
Normal file
28
release_notes/4.4.0.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Jasmine 4.4.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Optimized the process of transitioning between specs in Node, Safari, and
|
||||
Edge. This change reduces the run time of jasmine-core's own test suite by
|
||||
50-70% in Node, about 20% in Edge, and 75-90% in Safari. Your results may
|
||||
vary. In general, suites with many fast specs will see the greatest
|
||||
performance improvement.
|
||||
|
||||
* Removed old code to support browsers that don't provide
|
||||
addEventListener/removeEventListener.
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.4.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-15 |
|
||||
| Chrome | 105 |
|
||||
| Firefox | 91, 102, 104 |
|
||||
| Edge | 104 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
40
release_notes/4.5.0.md
Normal file
40
release_notes/4.5.0.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Jasmine 4.5.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Added Safari 16 to supported browsers
|
||||
* Include inner exceptions in stack traces
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Report exceptions thrown by a describe before any it calls
|
||||
* Coerce the random string to a seed before sending it to reporters
|
||||
* This fixes an error in HTMLReporter when the configured seed is a
|
||||
number rather than a string, which has been allowed since 3.8.0
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Fixed the jsdoc types of SuiteResult and SpecResult ids
|
||||
* Replaced var with const in API doc examples
|
||||
* Updated the style of the examples that are included in jasmine-core
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Converted TreeProcessor to async/await
|
||||
* Converted ReportDispatcher to promises
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.5.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-16 |
|
||||
| Chrome | 107 |
|
||||
| Firefox | 91, 102, 106 |
|
||||
| Edge | 106 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
19
release_notes/4.6.0.md
Normal file
19
release_notes/4.6.0.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Jasmine Core 4.6.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Report the ID of each suite/spec's parent
|
||||
* Report the path/url of the file that the spec/suite was defined in
|
||||
* Fixes [#1884](https://github.com/jasmine/jasmine/issues/1884)
|
||||
* Added Firefox 102 (current ESR) to supported browsers
|
||||
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Pinned sass to 1.58.3 for compatibility with Node 12
|
||||
* Pinned eslint-plugin-compat to <4.1.0 for compatibility with Node 12
|
||||
* Pinned Grunt to <1.6.0 for compatibility with Node 12
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
51
release_notes/4.6.1.md
Normal file
51
release_notes/4.6.1.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Jasmine Core 4.6.1 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This is a one-time backport of bug fixes from 5.x, for the benefit of Karma
|
||||
users who may not be aware that they're still using 4.x.
|
||||
|
||||
No further 4.x releases are planned. If possible, you should upgrade to the
|
||||
latest 5.x instead of 4.6.1. If you're using Karma, you can do this by
|
||||
installing jasmine-core 5.x and adding an override to package.json:
|
||||
|
||||
```
|
||||
{
|
||||
// ...
|
||||
"overrides": {
|
||||
"karma-jasmine": {
|
||||
"jasmine-core": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Removed unnecessary throw when building stack trace
|
||||
|
||||
* Fixed error when formatting Error object with non-Error cause property
|
||||
|
||||
Merges [#2013](https://github.com/jasmine/jasmine/pull/2013) from @angrycat9000.
|
||||
|
||||
Fixes [#2011](https://github.com/jasmine/jasmine/issues/2011).
|
||||
|
||||
* Accessibility: Always provide a non-color indication that a spec is pending
|
||||
|
||||
* Accessibility: Improved contrast of version number and inactive tab links
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 4.6.1 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 12.17+, 14, 16, 18 |
|
||||
| Safari | 14-16 |
|
||||
| Chrome | 125 |
|
||||
| Firefox | 91, 102, 126 |
|
||||
| Edge | 124 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
68
release_notes/5.0.0-alpha.0.md
Normal file
68
release_notes/5.0.0-alpha.0.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# Jasmine Core 5.0.0-alpha.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This release primarily adds support for parallel execution via the `jasmine`
|
||||
package. Please see its release notes and the
|
||||
[parallel documentation](https://jasmine.github.io/tutorials/running_specs_in_parallel)
|
||||
for more information. Additionally, this release cleans up a few outdated
|
||||
interfaces.
|
||||
|
||||
This is a pre-release for a major version. It contains breaking changes, and
|
||||
there may be further breaking changes between this release and the final 5.0.0
|
||||
release.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
* Use addEventListener in browsers rather than setting window.onerror
|
||||
|
||||
This simplifies error handling in browsers, makes Jasmine's own integration
|
||||
tests easier to debug, and provides stack traces for more unhandled
|
||||
exceptions. However, some browsers will provide less error information when
|
||||
the error comes from a file:// URL. Additionally, Jasmine will no longer
|
||||
override existing onerror handlers, and setting window.onerror will no longer
|
||||
override Jasmine's global error handling. (Use `jasmine.spyOnGlobalErrors`
|
||||
instead.)
|
||||
|
||||
* Made Env#execute async
|
||||
* Env#execute no longer takes a callback
|
||||
* The `boot` function exported by the core module returns the same object
|
||||
every time it's called.
|
||||
* Removed node_boot.js. Use the exported `boot` function instead.
|
||||
|
||||
### Changes to supported environments
|
||||
|
||||
The following previously supported environments are no longer supported:
|
||||
|
||||
* Node <16.14
|
||||
* Safari 14
|
||||
* Firefox 91
|
||||
|
||||
Although this release may still work in some of those environments, we no
|
||||
longer test against them and won't try to maintain compatibility with them in
|
||||
future releases.
|
||||
|
||||
## New features
|
||||
|
||||
* Support for parallel execution in Node.js using the `jasmine` package
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* The global error handler is uninstalled at the end of env execution.
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.0.0-alpha.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 16.14+, 18 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 111 |
|
||||
| Firefox | 102, 111 |
|
||||
| Edge | 111 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
39
release_notes/5.0.0-alpha.1.md
Normal file
39
release_notes/5.0.0-alpha.1.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Jasmine Core 5.0.0-alpha.1 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This release provides improved support for parallel execution via the `jasmine`
|
||||
package. Please see its release notes and the
|
||||
[parallel documentation](https://jasmine.github.io/tutorials/running_specs_in_parallel)
|
||||
for more information.
|
||||
|
||||
## New features and bug fixes
|
||||
|
||||
* Parallel: Cleaner interface for reporter dispatching
|
||||
* When Env#config is called from spec and helper files in parallel mode, throw
|
||||
an error rather than behaving unpredictably.
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* API reference docs for parallel support APIs that jasmine-npm uses
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Updated dev dependencies
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.0.0-alpha.1 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 16.14+, 18 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 112 |
|
||||
| Firefox | 102, 111 |
|
||||
| Edge | 111 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
28
release_notes/5.0.0-beta.0.md
Normal file
28
release_notes/5.0.0-beta.0.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Jasmine Core 5.0.0-beta.0 Release Notes
|
||||
|
||||
This release supports the 5.0.0-beta-0 release of the `jasmine` package.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
* Dropped support for Node 16
|
||||
|
||||
## New features
|
||||
|
||||
* Added support for Node 20
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.0.0-beta.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 112 |
|
||||
| Firefox | 102, 112 |
|
||||
| Edge | 112 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
55
release_notes/5.0.0.md
Normal file
55
release_notes/5.0.0.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Jasmine Core 5.0.0 Release Notes
|
||||
|
||||
## Summary
|
||||
|
||||
This is a major release that includes breaking changes. It primarily adds
|
||||
support for parallel execution in Node via the `jasmine` package. Most users
|
||||
should be able to upgrade without changes, but please read the list of breaking
|
||||
changes below and see the [migration guide](https://jasmine.github.io/tutorials/upgrading_to_Jasmine_5.0)
|
||||
for more information.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
* Dropped support for Node 12, 14, and 16
|
||||
* Dropped support for Safari 14 and Firefox 91
|
||||
* Made Env#execute async and removed the callback parameter
|
||||
* Global errors are detected via addEventListener rather than setting window.onerror
|
||||
* The `boot` function exported by the core module returns the same object
|
||||
every time it's called.
|
||||
* Removed node_boot.js. Use the exported `boot` function instead.
|
||||
|
||||
## New features
|
||||
|
||||
* Support for parallel execution in Node via the `jasmine` package
|
||||
See the [parallel guide](https://jasmine.github.io/tutorials/running_specs_in_parallel)
|
||||
for more information.
|
||||
* Added Node 20 to supported environments
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Accessibility: Always provide a non-color indication that a spec is pending
|
||||
* Accessibility: Improved contrast of version number and inactive tab links
|
||||
* Uninstall the global error handler at the end of env execution
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Updated dev dependencies
|
||||
* Dogfood parallel execution feature in CI
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.0.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 113 |
|
||||
| Firefox | 102, 113 |
|
||||
| Edge | 113 |
|
||||
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
25
release_notes/5.0.1.md
Normal file
25
release_notes/5.0.1.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Jasmine Core 5.0.1 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Optionally restore the pre-5.0 behavior of boot() always creating a new instance
|
||||
|
||||
This is needed by jasmine-npm (and likely other tools like it) that may
|
||||
need to create and use multiple envs in sequence.
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.0.1 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 114 |
|
||||
| Firefox | 102, 113 |
|
||||
| Edge | 113 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
39
release_notes/5.1.0.md
Normal file
39
release_notes/5.1.0.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Jasmine Core 5.1.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Exclude inherited Error properties from stack trace
|
||||
|
||||
* Fixed error when formatting Error object with non-Error cause property
|
||||
|
||||
Merges [#2013](https://github.com/jasmine/jasmine/pull/2013) from @angrycat9000.
|
||||
|
||||
Fixes [#2011](https://github.com/jasmine/jasmine/issues/2011).
|
||||
|
||||
* Added `throwUnless` and `throwUnlessAsync`
|
||||
|
||||
These are similar to `expect` and `expectAsync` except that they throw
|
||||
exceptions rather than recording matcher failures as spec/suite failures.
|
||||
They're intended to support using Jasmine matchers in [testing-library's](https://testing-library.com/)
|
||||
`waitFor`, and also provide a way to integration-test custom matchers.
|
||||
|
||||
Fixes [#2003](https://github.com/jasmine/jasmine/issues/2003).
|
||||
|
||||
Fixes [#1980](https://github.com/jasmine/jasmine/issues/1980).
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.1.0 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 114 |
|
||||
| Firefox | 102, 113 |
|
||||
| Edge | 113 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
28
release_notes/5.1.1.md
Normal file
28
release_notes/5.1.1.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Jasmine Core 5.1.1 Release Notes
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fixed global variable leak in the main process when running in parallel mode
|
||||
* Removed unnecessary throw when building expectation results
|
||||
|
||||
## Documentation Improvements
|
||||
|
||||
* Improved jsdocs for originalFn argument to createSpy
|
||||
* Link to 5.0 upgrade guide in README, not 4.0
|
||||
|
||||
## Supported environments
|
||||
|
||||
jasmine-core 5.1.1 has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-16 |
|
||||
| Chrome | 116 |
|
||||
| Firefox | 102, 116 |
|
||||
| Edge | 115 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
27
release_notes/5.1.2.md
Normal file
27
release_notes/5.1.2.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Jasmine Core 5.1.2 Release Notes
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fixed `throwUnlessAsync`
|
||||
* Fixes [#2026](https://github.com/jasmine/jasmine/issues/2026)
|
||||
|
||||
# Documentation improvements
|
||||
|
||||
* Added Safari 17 to supported browsers
|
||||
* Added Firefox 115 (current ESR) to supported browsers
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 121 |
|
||||
| Firefox | 102, 115, 122 |
|
||||
| Edge | 121 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
54
release_notes/5.10.0.md
Normal file
54
release_notes/5.10.0.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Jasmine Core 5.10.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Optionally detect promise rejections that are handled after an initial
|
||||
unhandled promise rejection event and don't report them as errors.
|
||||
This is off by default because it comes with a performance cost. It can be
|
||||
enabled by setting the `detectLateRejectionHandling` config property to true.
|
||||
* Add `getSpecProperty` to retrieve data that was set with `setSpecProperty`.
|
||||
* Merges [#2072](https://github.com/jasmine/jasmine/pull/2072) from @bonkevin
|
||||
* Show spec duration in the HTML reporter.
|
||||
* Merges [#2073](https://github.com/jasmine/jasmine/pull/2073) from @bonkevin
|
||||
* Protect `GlobalErrors` against monkey patching.
|
||||
|
||||
All currently shipped versions of zone.js contain a monkey patch that fails
|
||||
to pass constructor arguments on to `GlobalErrors`. This patch normally has
|
||||
no effect because zone.js is normally installed after `GlobalErrors` is
|
||||
instantiated, but it would crash Jasmine if it was applied early enough.
|
||||
|
||||
## Deprecations
|
||||
|
||||
* Issue a deprecation warning if the suite/spec order passed as a parameter to
|
||||
`Env#execute` causes a suite to be re-entered.
|
||||
|
||||
## Changes to supported environments
|
||||
|
||||
* Added Firefox 140 (current ESR) to supported environments
|
||||
* Demoted Firefox 128 (previous ESR) to best-effort support
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Core suite/spec execution flow has been significantly simplified.
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------------------|
|
||||
| Node | 18.20.5**, 20, 22, 24 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 139* |
|
||||
| Firefox | 102**, 115**, 128**, 140, 142* |
|
||||
| Edge | 139* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
66
release_notes/5.11.0.md
Normal file
66
release_notes/5.11.0.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Jasmine Core 5.11.0 Release Notes
|
||||
|
||||
## New features
|
||||
|
||||
* `detectLateRejectionHandling` works in `beforeAll` and `afterAll` as well as
|
||||
in specs.
|
||||
* Clicking a link in the HTML reporter does exact filtering rather than a
|
||||
substring match.
|
||||
|
||||
If you use jasmine-browser-runner or load boot1.js directly from jasmine-core,
|
||||
you'll get the new filtering behavior automatically. Otherwise, it requires
|
||||
several changes to boot1.js:
|
||||
|
||||
1. Add `queryString` to the options object passed to `HtmlReporter`, and
|
||||
remove `filterSpecs`.
|
||||
2. Instantiate a `jasmine.HtmlExactSpecFilter` instead of a
|
||||
`jasmine.HtmlSpecFilter`.
|
||||
2. Change the body of `config.specFilter` from
|
||||
`return specFilter.matches(spec.getFullName());` to
|
||||
`return specFilter.matches(spec)`
|
||||
|
||||
For a working example, see lib/jasmine-core/boot1.js in this package.
|
||||
Old boot1.js files will still work, but you'll get the old filtering behavior.
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Fixed global error handling when the env is executed repeatedly
|
||||
|
||||
## Changes to supported environments
|
||||
|
||||
* Safari 15 is no longer supported.
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Added API reference docs for classes used in browser boot files
|
||||
* Documented the order properties of `jasmineStarted` and `jasmineDone` events
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Unified top suite and regular suite execution
|
||||
* Converted `Spec`, `Suite`, and `QueryString` to ES6 classes
|
||||
* Extracted configuration out of `Env`
|
||||
* Updated tests to characterize suite/spec reporting more completely
|
||||
* Adopted `forbidDuplicateNames: true` in jasmine-core's own tests
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------------------|
|
||||
| Node | 18.20.5**, 20, 22, 24 |
|
||||
| Safari | 16**, 17** |
|
||||
| Chrome | 140* |
|
||||
| Firefox | 102**, 115**, 128**, 140, 143* |
|
||||
| Edge | 140* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
35
release_notes/5.2.0.md
Normal file
35
release_notes/5.2.0.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Jasmine Core 5.2.0 Release Notes
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fixed stack trace filtering in FF when the developer tools are open
|
||||
* Fixed handling of browser `error` events with message but no error
|
||||
|
||||
## New Features
|
||||
|
||||
* Improved the error message of the toHaveSize matcher.
|
||||
* Merges [#2033](https://github.com/jasmine/jasmine/pull/2033) from @stephanreiter
|
||||
* HTML reporter: show debug logs with white-space: pre
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Improved discoverability of asymmetric equality testers
|
||||
* Added an example for withContext()
|
||||
* Clarified spyOnGlobalErrorsAsync API docs
|
||||
* Added Node 22 to supported environments
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 126 |
|
||||
| Firefox | 102, 115, 128 |
|
||||
| Edge | 126 |
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
35
release_notes/5.3.0.md
Normal file
35
release_notes/5.3.0.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Jasmine Core 5.3.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Improved performance in Safari
|
||||
* Merges [#2040](https://github.com/jasmine/jasmine/pull/2040) from @dcsaszar
|
||||
* Fixes [#2008](https://github.com/jasmine/jasmine/issues/2008)
|
||||
|
||||
* Improved performance in Playwright Webkit on Windows
|
||||
* Merges [#2034](https://github.com/jasmine/jasmine/pull/2034) from @m-akinc
|
||||
|
||||
* Throw if spying has no effect, as when spying on localStorage methods in Firefox and Safari 17
|
||||
* See [#2036](https://github.com/jasmine/jasmine/issues/2036) and [#2007](https://github.com/jasmine/jasmine/issues/2007)
|
||||
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Added API reference for reporter capabilities
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 128 |
|
||||
| Firefox | 102, 115, 130 |
|
||||
| Edge | 128 |
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
39
release_notes/5.4.0.md
Normal file
39
release_notes/5.4.0.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# Jasmine Core 5.4.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Fixed de-duplication of exception messages containing blank lines on Node and Chrome
|
||||
|
||||
This is particularly helpful when reporting testing-library errors, which
|
||||
have messages that contain blank lines and can be hundreds or even thousands
|
||||
of lines long.
|
||||
|
||||
* Document that the expected and actual properties of expectation results are deprecated
|
||||
|
||||
The values of these properties are not reliable in configurations where
|
||||
reporter messages are JSON serialized. They appear to have been seldom if ever
|
||||
used. They will be removed in the next major release.
|
||||
|
||||
* Added Firefox 128 (current ESR) to supported browsers
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 129* |
|
||||
| Firefox | 102**, 115**, 128, 131* |
|
||||
| Edge | 129* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Environments that are past end of life are supported on a best-effort basis.
|
||||
They may be dropped in a future minor release of Jasmine if continued support
|
||||
becomes impractical.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
34
release_notes/5.5.0.md
Normal file
34
release_notes/5.5.0.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Jasmine Core 5.5.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Optionally enforce uniqueness of spec and suite names
|
||||
|
||||
This is off by default for backwards compatibility but can be enabled
|
||||
by setting the `forbidDuplicateNames` env config property to true.
|
||||
Fixes [#1633](https://github.com/jasmine/jasmine/issues/1633).
|
||||
|
||||
* Include property value mismatches in diffs even when there are missing or
|
||||
extra properties
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15-17 |
|
||||
| Chrome | 131* |
|
||||
| Firefox | 102**, 115**, 128, 132* |
|
||||
| Edge | 131* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Environments that are past end of life are supported on a best-effort basis.
|
||||
They may be dropped in a future minor release of Jasmine if continued support
|
||||
becomes impractical.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
51
release_notes/5.6.0.md
Normal file
51
release_notes/5.6.0.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Jasmine Core 5.6.0 Release Notes
|
||||
|
||||
## Changes
|
||||
|
||||
* Added [toHaveNoOtherSpyInteractions](https://jasmine.github.io/api/5.6/matchers.html#toHaveNoOtherSpyInteractions) matcher
|
||||
* Merges [#2051](https://github.com/jasmine/jasmine/pull/2051) from @Eradev
|
||||
* Fixes [#1991](https://github.com/jasmine/jasmine/issues/1991)
|
||||
|
||||
* Added [toBeNullish](https://jasmine.github.io/api/5.6/matchers.html#toBeNullish) matcher
|
||||
* Merges [#2045](https://github.com/jasmine/jasmine/pull/2045) from @MattMcCherry
|
||||
|
||||
* Improved error messages when non-promises are passed to built-in async matchers
|
||||
* Merges [#2049](https://github.com/jasmine/jasmine/pull/2049) from @andiz2
|
||||
* Fixes [#2037](https://github.com/jasmine/jasmine/issues/2037)
|
||||
|
||||
* Added [toHaveClasses](https://jasmine.github.io/api/5.6/matchers.html#toHaveClasses) matcher
|
||||
* Merges [#2046](https://github.com/jasmine/jasmine/pull/2046) from @aYorky
|
||||
|
||||
## Documentation updates
|
||||
|
||||
* Demoted Safari to best-effort support
|
||||
|
||||
Due to limited availability of Safari versions for contributors and maintainers
|
||||
as well as in CI, Safari will be supported on the same best-effort basis as
|
||||
environments that are past end of life, such as previous Firefox ESR versions.
|
||||
See [this discussion](https://github.com/jasmine/jasmine/discussions/2050) for
|
||||
more information about why this change was made and what to expect.
|
||||
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18, 20, 22 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 133* |
|
||||
| Firefox | 102**, 115**, 128, 135* |
|
||||
| Edge | 132* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
62
release_notes/5.7.0.md
Normal file
62
release_notes/5.7.0.md
Normal file
@@ -0,0 +1,62 @@
|
||||
# Jasmine Core 5.7.0 Release Notes
|
||||
|
||||
## New features
|
||||
|
||||
* Added [Clock#autoTick](https://jasmine.github.io/api/5.7/Clock.html#autoTick)
|
||||
to automatically tick the clock asynchronously
|
||||
* Merges #2042 from @atscott and @stephenfarrar
|
||||
* Fixes #1725
|
||||
|
||||
* Expose [spec path](https://jasmine.github.io/api/5.7/Spec.html#getPath) as an
|
||||
array of names in addition to the existing concatenated name
|
||||
|
||||
This is meant to support tools like IDE integrations that need to filter a run
|
||||
to an exact set of suites/specs.
|
||||
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Documented that [SpecResult#filename](https://jasmine.github.io/api/5.7/global.html#SpecResult)
|
||||
and [SuiteResult#filename](https://jasmine.github.io/api/5.7/global.html#SuiteResult)
|
||||
are wrong when zone.js is present and in some cases where it/describe/etc are
|
||||
replaced
|
||||
* Updated docs for expected and actual properties of
|
||||
[expectation results](https://jasmine.github.io/api/5.7/global.html#ExpectationResult)
|
||||
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Rewrote the build system to not use Grunt
|
||||
|
||||
Although Grunt has served Jasmine well over the years, it was keeping us tied
|
||||
to an aging and increasingly questionable set of dev dependencies.
|
||||
|
||||
* Updated to eslint 9
|
||||
* Removed mostly-unmaintained dev dependency 'temp'
|
||||
* Updated most other dev dependencies to latest versions
|
||||
* Fixed sass deprecation warning
|
||||
* Updated to Sauce Connect 5
|
||||
* Made stop-sauce-connect script more robust
|
||||
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18**, 20, 22 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 135* |
|
||||
| Firefox | 102**, 115**, 128, 137* |
|
||||
| Edge | 135* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
28
release_notes/5.7.1.md
Normal file
28
release_notes/5.7.1.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Jasmine Core 5.7.1 Release Notes
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Ensure that uninstalling the clock also stops auto tick
|
||||
* Merges #2057 from @atscott
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18**, 20, 22 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 136* |
|
||||
| Firefox | 102**, 115**, 128, 138* |
|
||||
| Edge | 135* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
44
release_notes/5.8.0.md
Normal file
44
release_notes/5.8.0.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Jasmine Core 5.8.0 Release Notes
|
||||
|
||||
## New Features
|
||||
|
||||
* Allow passing a function to `saveArgumentsByValue` to customize how arguments
|
||||
are saved
|
||||
* Merges [#2062](https://github.com/jasmine/jasmine/pull/2062) from @evanwaslh
|
||||
* Fixes [#1886](https://github.com/jasmine/jasmine/issues/1886)
|
||||
* Use custom object formatters in spy strategy mismatch errors
|
||||
* Include function names in pretty printer output
|
||||
* Improve performance of autoTick in Node
|
||||
* Merges [#2058](https://github.com/jasmine/jasmine/pull/2058) from @atscott
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
* Fix diff building when only one side has a custom object formatter
|
||||
* Fixes [#2061](https://github.com/jasmine/jasmine/issues/2061)
|
||||
|
||||
## Documentation improvements
|
||||
|
||||
* Added Node 24 to supported environments
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18**, 20, 22, 24 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 137* |
|
||||
| Firefox | 102**, 115**, 128, 139* |
|
||||
| Edge | 137* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
56
release_notes/5.9.0.md
Normal file
56
release_notes/5.9.0.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Jasmine Core 5.9.0 Release Notes
|
||||
|
||||
## Bug fixes
|
||||
|
||||
* Avoid generating mock clock timer IDs that conflict with native ones
|
||||
* Fixes [#2068](https://github.com/jasmine/jasmine/issues/2068)
|
||||
* Merges [#2069](https://github.com/jasmine/jasmine/pull/2069) from @atscott
|
||||
|
||||
## Deprecations and changes to platform support
|
||||
|
||||
* Node versions before 18.20.5 are no longer supported
|
||||
|
||||
Older 18.x versions might still work, but Jasmine is no longer tested in them
|
||||
prior to release.
|
||||
* Document that the filename properties of suite and spec results are deprecated
|
||||
|
||||
These properties are incorrect in many configurations. They'll be removed in
|
||||
the next major release unless there is enough user interest in fixing them.
|
||||
See <https://github.com/jasmine/jasmine/issues/2065>.
|
||||
|
||||
## Internal improvements
|
||||
|
||||
* Extensive GlobalErrors refactoring
|
||||
* Removed many of the error dispatching differences between browsers and Node
|
||||
* Split into portable and platform-specific parts
|
||||
* Converted to ES6 classes
|
||||
* Removed unnecessary errorWithStack helper
|
||||
|
||||
Jasmine no longer runs on platforms that create errors without stack traces.
|
||||
* Removed protections against user code redefining undefined
|
||||
|
||||
Jasmine no longer runs on platforms that allow redefining undefined.
|
||||
* Removed rimraf and shelljs dev dependencies
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|-------------------------|
|
||||
| Node | 18.20.5**, 20, 22, 24 |
|
||||
| Safari | 15**, 16**, 17** |
|
||||
| Chrome | 138* |
|
||||
| Firefox | 102**, 115**, 128, 140* |
|
||||
| Edge | 138* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
100
release_notes/6.0.0-alpha.0.md
Normal file
100
release_notes/6.0.0-alpha.0.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Jasmine Core 6.0.0-alpha.0 Release Notes
|
||||
|
||||
This is a pre-release, intended to offer a preview of breaking changes and to
|
||||
solicit feedback.
|
||||
|
||||
## A Note About Pre-Release Compatibility
|
||||
|
||||
There may be additional breaking changes in future 6.0 pre-releases or in the
|
||||
final 6.0 release. That's allowed by the semver specification, but users are
|
||||
sometimes unpleasantly surprised by it.
|
||||
|
||||
NPM's implementation of carat version ranges assumes that subsequent
|
||||
pre-releases and final releases are fully compatible with earlier pre-releases.
|
||||
If your package.json contains `"jasmine-core": "^6.0.0-alpha.0`,
|
||||
NPM might install any later 6.x version even though there is no guarantee of
|
||||
compatibility. If that isn't ok, you should specify an exact pre-release version:
|
||||
`"jasmine-core": "6.0.0-alpha.0`.
|
||||
|
||||
## Changes to supported environments
|
||||
|
||||
* Node 18 is no longer supported.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
### General
|
||||
|
||||
* Private APIs have been removed from the `jasmine` namespace.
|
||||
|
||||
The purpose of this change is to reduce the risk of users inadvertently
|
||||
depending on private APIs. Anything that's not covered by
|
||||
[the documentation](https://jasmine.github.io/pages/docs_home.html) remains
|
||||
private regardless of namespacing. Private APIs may be changed or removed in
|
||||
any release. This change is being made in a major release as a courtesy to users of
|
||||
libraries that depend on private APIs.
|
||||
|
||||
* Arguments to `setSpecProperty`/`setSuiteProperty` must be both
|
||||
structured-cloneable and JSON-serializable.
|
||||
* Mock clock timing functions cannot be spied on. Previously this "worked" but
|
||||
prevented the mock clock from uninstalling itself.
|
||||
* The default value of the `forbidDuplicateNames` config option has been
|
||||
changed to true.
|
||||
* The mock clock no longer supports the eval forms of `setTimeout` and
|
||||
`setInterval`.
|
||||
* If an execution order is passed to `Env#execute`, it must not enter any suite
|
||||
more than once.
|
||||
* The argument passed to spec filters is a
|
||||
[spec metadata](https://jasmine.github.io/api/6.0.0-alpha.0/Spec.html)
|
||||
instance, not the internal spec object.
|
||||
|
||||
### Changes that affect reporters
|
||||
|
||||
This release includes changes that are intended to streamline and clarify the
|
||||
reporter interface, prevent sharing of mutable state, and prevent bugs involving
|
||||
non-serializable objects. These changes should be compatible with most existing
|
||||
reporters but could break reporters that manage their internal state in unusual
|
||||
ways. Please [open an issue](https://github.com/jasmine/jasmine/issues/new?template=bug_report.yml)
|
||||
if you find a published reporter package that works with jasmine-core 5.x but
|
||||
not with this release.
|
||||
|
||||
* Irrelevant properties such as `status` and `failedExpectations` are omitted
|
||||
from [the event passed to specStarted](https://jasmine.github.io/api/6.0.0-alpha.0/global.html#SpecStartedEvent).
|
||||
* Reporter events are deep-cloned before being passed to each reporter. This
|
||||
protects reporters against later mutation by jasmine-core or other reporters.
|
||||
* The `expected` and `actual` properties of
|
||||
[passed and failed expectations](https://jasmine.github.io/api/6.0.0-alpha.0/global.html#ExpectationResult)
|
||||
have been removed.
|
||||
* The [order](https://jasmine.github.io/api/6.0.0-alpha.0/global.html#Order)
|
||||
property of the`jasmineStarted` and `jasmineDone` reporter events no longer
|
||||
includes undocumented properties.
|
||||
|
||||
### Changes to Node boot functions
|
||||
|
||||
* [boot](https://jasmine.github.io/api/6.0.0-alpha.0/module-jasmine-core.html#.boot)
|
||||
defaults to creating a new core instance each time it's called. This restores
|
||||
the pre-5.0 default behavior.
|
||||
* [noGlobals](https://jasmine.github.io/api/6.0.0-alpha.0/module-jasmine-core.html#.noGlobals)
|
||||
no longer takes a parameter. It always returns the same object when called
|
||||
repeatedly.
|
||||
|
||||
## Supported environments
|
||||
|
||||
This version has been tested in the following environments.
|
||||
|
||||
| Environment | Supported versions |
|
||||
|-------------------|--------------------------------|
|
||||
| Node | 20, 22, 24 |
|
||||
| Safari | 16**, 17** |
|
||||
| Chrome | 140* |
|
||||
| Firefox | 102**, 115**, 128**, 140, 143* |
|
||||
| Edge | 140* |
|
||||
|
||||
\* Evergreen browser. Each version of Jasmine is tested against the latest
|
||||
version available at release time.<br>
|
||||
\** Supported on a best-effort basis. Support for these versions may be dropped
|
||||
if it becomes impractical, and bugs affecting only these versions may not be
|
||||
treated as release blockers.
|
||||
|
||||
------
|
||||
|
||||
_Release Notes generated with _[Anchorman](http://github.com/infews/anchorman)_
|
||||
3
scripts/buildDistribution.js
Normal file
3
scripts/buildDistribution.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const buildDistribution = require('./lib/buildDistribution');
|
||||
|
||||
buildDistribution();
|
||||
86
scripts/buildStandaloneDist.js
Normal file
86
scripts/buildStandaloneDist.js
Normal file
@@ -0,0 +1,86 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const glob = require('glob');
|
||||
const ejs = require('ejs');
|
||||
const archiver = require('archiver');
|
||||
const buildDistribution = require('./lib/buildDistribution');
|
||||
|
||||
const prefix = path.join(os.tmpdir(), 'jasmine-build-standalone');
|
||||
const tmpDir = fs.mkdtempSync(prefix);
|
||||
|
||||
buildStandaloneDist().finally(function() {
|
||||
fs.rmSync(tmpDir, { recursive: true });
|
||||
});
|
||||
|
||||
async function buildStandaloneDist() {
|
||||
buildDistribution();
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json'));
|
||||
compileSpecRunner(pkg.version);
|
||||
await zipStandaloneDist(pkg.version);
|
||||
}
|
||||
|
||||
function compileSpecRunner(jasmineVersion) {
|
||||
const template = fs.readFileSync('src/SpecRunner.html.ejs',
|
||||
{encoding: 'utf8'});
|
||||
const runnerHtml = ejs.render(template, { jasmineVersion });
|
||||
fs.writeFileSync(path.join(tmpDir, 'SpecRunner.html'), runnerHtml,
|
||||
{encoding: 'utf8'});
|
||||
}
|
||||
|
||||
async function zipStandaloneDist(jasmineVersion) {
|
||||
const fileGroups = [
|
||||
{
|
||||
src: [
|
||||
'LICENSE',
|
||||
path.join(tmpDir, 'SpecRunner.html'),
|
||||
]
|
||||
},
|
||||
{
|
||||
src: [
|
||||
'images/jasmine_favicon.png',
|
||||
'lib/jasmine-core/jasmine.js',
|
||||
'lib/jasmine-core/jasmine-html.js',
|
||||
'lib/jasmine-core/jasmine.css',
|
||||
'lib/jasmine-core/boot0.js',
|
||||
'lib/jasmine-core/boot1.js',
|
||||
],
|
||||
destDir: 'lib/jasmine-' + jasmineVersion
|
||||
},
|
||||
{
|
||||
src: glob.sync('lib/jasmine-core/example/src/*.js'),
|
||||
destDir: 'src'
|
||||
},
|
||||
{
|
||||
src: glob.sync('lib/jasmine-core/example/spec/*.js'),
|
||||
destDir: 'spec'
|
||||
}
|
||||
];
|
||||
|
||||
const destPath = `./dist/jasmine-standalone-${jasmineVersion}.zip`;
|
||||
const output = fs.createWriteStream(destPath);
|
||||
const archive = archiver('zip');
|
||||
|
||||
const done = new Promise(function(resolve, reject) {
|
||||
output.on('close', resolve);
|
||||
archive.on('warning', reject);
|
||||
archive.on('error', reject);
|
||||
});
|
||||
|
||||
archive.pipe(output);
|
||||
|
||||
for (const group of fileGroups) {
|
||||
for (const srcPath of group.src) {
|
||||
let destPath = path.basename(srcPath);
|
||||
|
||||
if (group.destDir) {
|
||||
destPath = `${group.destDir}/${destPath}`;
|
||||
}
|
||||
|
||||
archive.file(srcPath, {name: destPath});
|
||||
}
|
||||
}
|
||||
|
||||
archive.finalize();
|
||||
await done;
|
||||
}
|
||||
133
scripts/lib/buildDistribution.js
Normal file
133
scripts/lib/buildDistribution.js
Normal file
@@ -0,0 +1,133 @@
|
||||
const fs = require('fs');
|
||||
const sass = require('sass');
|
||||
const glob = require('glob');
|
||||
const ejs = require('ejs');
|
||||
const cssUrlEmbed = require('css-url-embed');
|
||||
|
||||
function buildDistribution() {
|
||||
compileSass();
|
||||
embedCssAssets();
|
||||
concatFiles();
|
||||
}
|
||||
|
||||
function embedCssAssets() {
|
||||
const cssPath = 'lib/jasmine-core/jasmine.css';
|
||||
cssUrlEmbed.processFile(cssPath, cssPath, function(filePath) {
|
||||
if (filePath.endsWith('.png')) {
|
||||
return 'image/png';
|
||||
} else if (filePath.endsWith('.svg')) {
|
||||
return 'image/svg+xml';
|
||||
} else {
|
||||
throw new Error(`Don't know MIME type for file: ${filePath}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function compileSass() {
|
||||
const output = sass.compile('src/html/jasmine.scss');
|
||||
fs.writeFileSync('lib/jasmine-core/jasmine.css', output.css,
|
||||
{encoding: 'utf8'});
|
||||
}
|
||||
|
||||
function concatFiles() {
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json'));
|
||||
const configs = [
|
||||
{
|
||||
src: [
|
||||
'src/html/requireHtml.js',
|
||||
'src/html/HtmlReporter.js',
|
||||
'src/html/HtmlSpecFilter.js',
|
||||
'src/html/ResultsNode.js',
|
||||
'src/html/QueryString.js',
|
||||
'src/html/**/*.js'
|
||||
],
|
||||
dest: 'lib/jasmine-core/jasmine-html.js',
|
||||
},
|
||||
{
|
||||
dest: 'lib/jasmine-core/jasmine.js',
|
||||
src: [
|
||||
'src/core/requireCore.js',
|
||||
'src/core/matchers/requireMatchers.js',
|
||||
'src/core/base.js',
|
||||
'src/core/util.js',
|
||||
'src/core/Spec.js',
|
||||
'src/core/Order.js',
|
||||
'src/core/Env.js',
|
||||
'src/core/JsApiReporter.js',
|
||||
'src/core/PrettyPrinter',
|
||||
'src/core/Suite',
|
||||
'src/core/**/*.js',
|
||||
{
|
||||
template: 'src/version.js',
|
||||
data: {version: pkg.version}
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
dest: 'lib/jasmine-core/boot0.js',
|
||||
src: ['src/boot/boot0.js'],
|
||||
},
|
||||
{
|
||||
dest: 'lib/jasmine-core/boot1.js',
|
||||
src: ['src/boot/boot1.js'],
|
||||
},
|
||||
{
|
||||
dest: 'lib/jasmine-core.js',
|
||||
src: ['src/boot/jasmine-core.js'],
|
||||
}
|
||||
];
|
||||
const licenseBanner = {
|
||||
template: 'src/licenseBanner.js.ejs',
|
||||
data: {currentYear: new Date(Date.now()).getFullYear()}
|
||||
};
|
||||
|
||||
for (const {src, dest} of configs) {
|
||||
src.unshift(licenseBanner);
|
||||
|
||||
function expand(srcListEntry) {
|
||||
if (typeof srcListEntry === 'object') {
|
||||
return srcListEntry;
|
||||
}
|
||||
|
||||
return glob.sync(srcListEntry)
|
||||
.sort(function (a, b) {
|
||||
// Match the sort order of previous build tools, so that the
|
||||
// output is the same.
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
|
||||
if (a < b) {
|
||||
return -1;
|
||||
} else if (a === b) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const srcs = src.flatMap(expand);
|
||||
const seen = new Set();
|
||||
const chunks = [];
|
||||
|
||||
for (const s of srcs) {
|
||||
let content;
|
||||
|
||||
if (!seen.has(s)) {
|
||||
if (s.template) {
|
||||
const template = fs.readFileSync(s.template, {encoding: 'utf8'});
|
||||
content = ejs.render(template, s.data);
|
||||
} else {
|
||||
content = fs.readFileSync(s, {encoding: 'utf8'});
|
||||
}
|
||||
|
||||
chunks.push(content);
|
||||
seen.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(dest, chunks.join('\n'), {encoding: 'utf8'});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = buildDistribution;
|
||||
@@ -3,6 +3,7 @@
|
||||
run_browser() {
|
||||
browser=$1
|
||||
version=$2
|
||||
os="$3"
|
||||
description="$browser $version"
|
||||
if [ $version = "latest" ]; then
|
||||
version=""
|
||||
@@ -12,7 +13,7 @@ run_browser() {
|
||||
echo
|
||||
echo "Running $description"
|
||||
echo
|
||||
USE_SAUCE=true JASMINE_BROWSER=$browser SAUCE_BROWSER_VERSION=$version npm run ci
|
||||
USE_SAUCE=true JASMINE_BROWSER=$browser SAUCE_BROWSER_VERSION=$version SAUCE_OS="$os" npm run ci
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "PASS: $description" >> "$passfile"
|
||||
@@ -23,11 +24,24 @@ run_browser() {
|
||||
|
||||
passfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
|
||||
failfile=`mktemp -t jasmine-results.XXXXXX` || exit 1
|
||||
|
||||
run_browser chrome latest
|
||||
|
||||
run_browser firefox latest
|
||||
run_browser firefox 91
|
||||
run_browser safari 15
|
||||
run_browser safari 14
|
||||
if [ "$1" = "--not-actually-all" ]; then
|
||||
echo "SKIPPED: firefox 140" >> "$passfile"
|
||||
echo "SKIPPED: firefox 128" >> "$passfile"
|
||||
echo "SKIPPED: firefox 115" >> "$passfile"
|
||||
else
|
||||
run_browser firefox 140
|
||||
run_browser firefox 128
|
||||
run_browser firefox 115
|
||||
fi
|
||||
run_browser firefox 102
|
||||
|
||||
run_browser safari 17
|
||||
run_browser safari 16
|
||||
|
||||
run_browser MicrosoftEdge latest
|
||||
|
||||
echo
|
||||
|
||||
28
scripts/runSpecsInNode.js
Normal file
28
scripts/runSpecsInNode.js
Normal file
@@ -0,0 +1,28 @@
|
||||
verifyNoGlobals(() => require('../lib/jasmine-core.js').noGlobals());
|
||||
|
||||
const Jasmine = require('jasmine');
|
||||
const jasmineCore = require('../lib/jasmine-core.js');
|
||||
const runner = new Jasmine({jasmineCore: jasmineCore});
|
||||
|
||||
runner.loadConfigFile('./spec/support/jasmine.json');
|
||||
runner.exitOnCompletion = false;
|
||||
runner.execute()
|
||||
.then(
|
||||
result => result.overallStatus === 'passed',
|
||||
err => {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
)
|
||||
.then(ok => process.exit(ok ? 0 : 1));
|
||||
|
||||
function verifyNoGlobals(fn) {
|
||||
const initialGlobals = Object.keys(global);
|
||||
fn();
|
||||
|
||||
const extras = Object.keys(global).filter(k => !initialGlobals.includes(k));
|
||||
|
||||
if (extras.length !== 0) {
|
||||
throw new Error('Globals were unexpectedly created: ' + extras.join(', '));
|
||||
}
|
||||
}
|
||||
28
scripts/runSpecsInParallel.js
Normal file
28
scripts/runSpecsInParallel.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const ParallelRunner = require('jasmine/parallel');
|
||||
const jasmineCore = require('../lib/jasmine-core.js');
|
||||
let numWorkers = require('os').cpus().length;
|
||||
|
||||
if (process.env['CIRCLECI']) {
|
||||
// On Circle CI, the above gives the number of CPU cores on the host
|
||||
// computer, which is unrelated to the resources actually available
|
||||
// to the container. 2 workers gives peak performance with our current
|
||||
// configuration, but 4 might increase the odds of discovering any
|
||||
// parallel-specific bugs.
|
||||
numWorkers = 4;
|
||||
}
|
||||
|
||||
const runner = new ParallelRunner({jasmineCore, numWorkers});
|
||||
|
||||
runner.loadConfigFile('./spec/support/jasmine.json')
|
||||
.then(() => {
|
||||
runner.exitOnCompletion = false;
|
||||
return runner.execute();
|
||||
})
|
||||
.then(
|
||||
jasmineDoneInfo => jasmineDoneInfo.overallStatus === 'passed',
|
||||
err => {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
)
|
||||
.then(ok => process.exit(ok ? 0 : 1));
|
||||
@@ -2,32 +2,19 @@
|
||||
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"
|
||||
if [ -z "$SAUCE_TUNNEL_NAME" ]; then
|
||||
echo "SAUCE_TUNNEL_NAME must be set" 1>&2
|
||||
exit 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
|
||||
sc legacy --proxy-localhost --tunnel-domains localhost --region us-west \
|
||||
-u "$SAUCE_USERNAME" -k "$SAUCE_ACCESS_KEY" \
|
||||
-X 4445 -i "$SAUCE_TUNNEL_NAME" 2>&1 | tee "$outfile" &
|
||||
|
||||
while ! fgrep "Sauce Connect is up, you may start your tests." "$outfile" > /dev/null; do
|
||||
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
|
||||
|
||||
@@ -2,32 +2,38 @@
|
||||
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
|
||||
|
||||
# Sauce Connect 4 docs said that we can just kill -9 it if we don't care about
|
||||
# failing any ongoing sessions. In practice, that sometimes worked but usually
|
||||
# leaked a tunnel so badly that you couldn't even stop it from the web UI.
|
||||
#
|
||||
# Sauce Connect 5 appears to be *much* more prone to hung jobs. Hung jobs have
|
||||
# a shutdown deadline of *three hours*, however, they appear to usually exit
|
||||
# within a minute or so. Unfortunately the only thing the Sauce Connect 5 docs
|
||||
# say about shutdown is that "you can stop your tunnel from the terminal where
|
||||
# Sauce Connect is running by entering Ctrl+C". Nothing is said about what to
|
||||
# do if Sauce Connect doesn't exit on it own or about non-interactive usage.
|
||||
#
|
||||
# So we do our best to be well-behaved without assuming that Sauce Connect
|
||||
# always is: send it the same signal that it would get if an interactive user
|
||||
# hit ctrl-c, wait a while for it to exit, then give up so that the CI task
|
||||
# doesn't keep running indefinitely.
|
||||
|
||||
if ! pkill -INT '^sc$'; then
|
||||
echo "sc does not appear to be running" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 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
|
||||
while [ $n -lt 120 ] && pgrep '^sc$' > /dev/null; do
|
||||
sleep 1
|
||||
kill -INT $pid 2> /dev/null || true
|
||||
pkill -INT '^sc$' || true
|
||||
n=$(($n + 1))
|
||||
done
|
||||
|
||||
if ps -p $pid > /dev/null; then
|
||||
if pgrep '^sc$' > /dev/null; then
|
||||
echo "Could not shut down Sauce Connect"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit $exitcode
|
||||
|
||||
@@ -14,8 +14,6 @@ module.exports = {
|
||||
// TODO: consider doing this in src files as well as specs
|
||||
'no-unused-vars': ['error', { args: 'after-used' }],
|
||||
|
||||
'no-var': 'error',
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
describe('AsyncExpectation', function() {
|
||||
beforeEach(function() {
|
||||
jasmineUnderTest.Expectation.addAsyncCoreMatchers(
|
||||
jasmineUnderTest.asyncMatchers
|
||||
privateUnderTest.Expectation.addAsyncCoreMatchers(
|
||||
privateUnderTest.asyncMatchers
|
||||
);
|
||||
});
|
||||
|
||||
@@ -9,9 +9,9 @@ describe('AsyncExpectation', function() {
|
||||
it('converts a pass to a fail', function() {
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = Promise.resolve(),
|
||||
pp = jasmineUnderTest.makePrettyPrinter(),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp }),
|
||||
pp = privateUnderTest.makePrettyPrinter(),
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: new privateUnderTest.MatchersUtil({ pp: pp }),
|
||||
actual: actual,
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
@@ -29,9 +29,9 @@ describe('AsyncExpectation', function() {
|
||||
|
||||
it('converts a fail to a pass', function() {
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = Promise.reject(),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: new jasmineUnderTest.MatchersUtil({
|
||||
actual = Promise.reject(new Error('nope')),
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: new privateUnderTest.MatchersUtil({
|
||||
pp: function() {}
|
||||
}),
|
||||
actual: actual,
|
||||
@@ -55,7 +55,7 @@ describe('AsyncExpectation', function() {
|
||||
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = dummyPromise(),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: actual,
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
@@ -80,7 +80,7 @@ describe('AsyncExpectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: Promise.reject('rejected'),
|
||||
addExpectationResult: addExpectationResult,
|
||||
matchersUtil: matchersUtil
|
||||
@@ -105,10 +105,10 @@ describe('AsyncExpectation', function() {
|
||||
buildFailureMessage: function() {
|
||||
return 'failure message';
|
||||
},
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
pp: privateUnderTest.makePrettyPrinter()
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: Promise.reject('b'),
|
||||
addExpectationResult: addExpectationResult,
|
||||
matchersUtil: matchersUtil
|
||||
@@ -129,43 +129,43 @@ describe('AsyncExpectation', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('prepends the context to a custom failure message from a function', function() {
|
||||
pending('should actually work, but no custom matchers for async yet');
|
||||
|
||||
it('prepends the context to a custom failure message from a matcher', async function() {
|
||||
const matchersUtil = {
|
||||
buildFailureMessage: function() {
|
||||
return 'failure message';
|
||||
}
|
||||
buildFailureMessage() {
|
||||
return 'failure message';
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = Promise.reject(),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
actual: actual,
|
||||
addExpectationResult: addExpectationResult,
|
||||
matchersUtil: matchersUtil
|
||||
});
|
||||
pp(v) {
|
||||
return v.toString();
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
const actual = Promise.reject(new Error('nope'));
|
||||
const expectation = privateUnderTest.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'
|
||||
})
|
||||
);
|
||||
});
|
||||
await expectation.withContext('Some context').toBeResolved();
|
||||
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(
|
||||
false,
|
||||
jasmine.objectContaining({
|
||||
message:
|
||||
'Some context: Expected a promise to be resolved but it ' +
|
||||
'was rejected with Error: nope.'
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it('works with #not', function() {
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = Promise.resolve(),
|
||||
pp = jasmineUnderTest.makePrettyPrinter(),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
pp = privateUnderTest.makePrettyPrinter(),
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: actual,
|
||||
addExpectationResult: addExpectationResult,
|
||||
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp })
|
||||
matchersUtil: new privateUnderTest.MatchersUtil({ pp: pp })
|
||||
});
|
||||
|
||||
return expectation
|
||||
@@ -185,11 +185,11 @@ describe('AsyncExpectation', function() {
|
||||
it('works with #not and a custom message', function() {
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = Promise.resolve('a'),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: actual,
|
||||
addExpectationResult: addExpectationResult,
|
||||
matchersUtil: new jasmineUnderTest.MatchersUtil({
|
||||
pp: jasmineUnderTest.makePrettyPrinter()
|
||||
matchersUtil: new privateUnderTest.MatchersUtil({
|
||||
pp: privateUnderTest.makePrettyPrinter()
|
||||
})
|
||||
});
|
||||
|
||||
@@ -214,7 +214,7 @@ describe('AsyncExpectation', function() {
|
||||
toFoo: function() {},
|
||||
toBar: function() {}
|
||||
},
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: asyncMatchers
|
||||
});
|
||||
|
||||
@@ -236,7 +236,7 @@ describe('AsyncExpectation', function() {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: matchersUtil,
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
@@ -263,7 +263,7 @@ describe('AsyncExpectation', function() {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
matchersUtil: matchersUtil,
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
@@ -277,25 +277,20 @@ describe('AsyncExpectation', function() {
|
||||
|
||||
it('reports a passing result to the spec when the comparison passes', function() {
|
||||
const matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
matchersUtil = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
errorWithStack = new Error('errorWithStack');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const matchersUtil = {
|
||||
buildFailureMessage: jasmine.createSpy('buildFailureMessage')
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
matchersUtil: matchersUtil,
|
||||
actual: 'an actual',
|
||||
@@ -308,9 +303,7 @@ describe('AsyncExpectation', function() {
|
||||
passed: true,
|
||||
message: '',
|
||||
error: undefined,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -329,15 +322,10 @@ describe('AsyncExpectation', function() {
|
||||
buildFailureMessage: function() {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
errorWithStack = new Error('errorWithStack');
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
matchersUtil: matchersUtil,
|
||||
actual: 'an actual',
|
||||
@@ -348,36 +336,29 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: '',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a failing result and a custom fail message to the spec when the comparison fails', function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: false,
|
||||
message: 'I am a custom message'
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: 'an actual',
|
||||
customAsyncMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -387,38 +368,31 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a failing result with a custom fail message function to the spec when the comparison fails', function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: false,
|
||||
message: function() {
|
||||
return 'I am a custom message';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -428,34 +402,26 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a passing result to the spec when the comparison fails for a negative expectation', function() {
|
||||
const matchers = {
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: false });
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual',
|
||||
errorWithStack = new Error('errorWithStack');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: false });
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -467,9 +433,7 @@ describe('AsyncExpectation', function() {
|
||||
passed: true,
|
||||
message: '',
|
||||
error: undefined,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -488,16 +452,10 @@ describe('AsyncExpectation', function() {
|
||||
buildFailureMessage: function() {
|
||||
return 'default message';
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual',
|
||||
errorWithStack = new Error('errorWithStack');
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
matchersUtil: matchersUtil,
|
||||
@@ -508,37 +466,29 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: 'default message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('reports a failing result and a custom fail message to the spec when the comparison passes for a negative expectation', function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: true,
|
||||
message: 'I am a custom message'
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -548,37 +498,29 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a passing result to the spec when the 'not' comparison passes, given a negativeCompare", function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
},
|
||||
negativeCompare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -588,40 +530,32 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
||||
matcherName: 'toFoo',
|
||||
passed: true,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: '',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a failing result and a custom fail message to the spec when the 'not' comparison fails, given a negativeCompare", function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({ pass: true });
|
||||
},
|
||||
negativeCompare: function() {
|
||||
return Promise.resolve({
|
||||
pass: false,
|
||||
message: "I'm a custom message"
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
customAsyncMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -631,11 +565,9 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: "I'm a custom message",
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -643,26 +575,21 @@ describe('AsyncExpectation', function() {
|
||||
it('reports errorWithStack when a custom error message is returned', function() {
|
||||
const customError = new Error('I am a custom error');
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: false,
|
||||
message: 'I am a custom message',
|
||||
error: customError
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: 'an actual',
|
||||
customAsyncMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -672,36 +599,29 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a custom message to the spec when a 'not' comparison fails", function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: true,
|
||||
message: 'I am a custom message'
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
const expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: 'an actual',
|
||||
customAsyncMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -711,38 +631,31 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("reports a custom message func to the spec when a 'not' comparison fails", function() {
|
||||
const 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');
|
||||
toFoo: function() {
|
||||
return {
|
||||
compare: function() {
|
||||
return Promise.resolve({
|
||||
pass: true,
|
||||
message: function() {
|
||||
return 'I am a custom message';
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
const addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
spyOn(jasmineUnderTest.util, 'errorWithStack').and.returnValue(
|
||||
errorWithStack
|
||||
);
|
||||
|
||||
let expectation = jasmineUnderTest.Expectation.asyncFactory({
|
||||
let expectation = privateUnderTest.Expectation.asyncFactory({
|
||||
actual: 'an actual',
|
||||
customAsyncMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -752,11 +665,9 @@ describe('AsyncExpectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: errorWithStack
|
||||
errorForStack: jasmine.any(Error)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
describe('CallTracker', function() {
|
||||
it('tracks that it was called when executed', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
expect(callTracker.any()).toBe(false);
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('tracks that number of times that it is executed', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
expect(callTracker.count()).toEqual(0);
|
||||
|
||||
@@ -20,7 +20,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('tracks the params from each execution', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track({ object: void 0, args: [] });
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
@@ -31,7 +31,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it("tracks the 'this' object from each execution", function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
const this0 = {},
|
||||
this1 = {};
|
||||
@@ -45,13 +45,13 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('returns any empty array when there was no call', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
expect(callTracker.argsFor(0)).toEqual([]);
|
||||
});
|
||||
|
||||
it('allows access for the arguments for all calls', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track({ object: {}, args: [] });
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
@@ -60,7 +60,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('tracks the context and arguments for each call', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track({ object: {}, args: [] });
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
@@ -71,7 +71,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('simplifies access to the arguments for the last (most recent) call', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track();
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
@@ -83,13 +83,13 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it("returns a useful falsy value when there isn't a last (most recent) call", function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
expect(callTracker.mostRecent()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('simplifies access to the arguments for the first (oldest) call', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
|
||||
@@ -97,13 +97,13 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it("returns a useful falsy value when there isn't a first (oldest) call", function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
expect(callTracker.first()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('allows the tracking to be reset', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
|
||||
callTracker.track();
|
||||
callTracker.track({ object: {}, args: [0, 'foo'] });
|
||||
@@ -117,7 +117,7 @@ describe('CallTracker', function() {
|
||||
});
|
||||
|
||||
it('allows object arguments to be shallow cloned', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker();
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
callTracker.saveArgumentsByValue();
|
||||
|
||||
const objectArg = { foo: 'bar' },
|
||||
@@ -134,8 +134,44 @@ describe('CallTracker', function() {
|
||||
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
||||
});
|
||||
|
||||
it('allows object arguments to be deep cloned', function() {
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
callTracker.saveArgumentsByValue(args => JSON.parse(JSON.stringify(args)));
|
||||
|
||||
const objectArg = { foo: { bar: { baz: ['qux'] } } },
|
||||
arrayArg = ['foo', 'bar'];
|
||||
|
||||
callTracker.track({
|
||||
object: {},
|
||||
args: [objectArg, arrayArg, false, undefined, null, NaN, '', 0, 1.0]
|
||||
});
|
||||
|
||||
objectArg.foo.bar.baz.push('quux');
|
||||
|
||||
expect(callTracker.mostRecent().args[0]).not.toBe(objectArg);
|
||||
expect(callTracker.mostRecent().args[0]).not.toEqual(objectArg);
|
||||
expect(callTracker.mostRecent().args[0]).toEqual({
|
||||
foo: { bar: { baz: ['qux'] } }
|
||||
});
|
||||
expect(callTracker.mostRecent().args[1]).not.toBe(arrayArg);
|
||||
expect(callTracker.mostRecent().args[1]).toEqual(arrayArg);
|
||||
});
|
||||
|
||||
it('can take any function to transform arguments when saving by value', function() {
|
||||
const callTracker = new privateUnderTest.CallTracker();
|
||||
callTracker.saveArgumentsByValue(JSON.stringify);
|
||||
|
||||
const objectArg = { foo: { bar: { baz: ['qux'] } } },
|
||||
arrayArg = ['foo', 'bar'],
|
||||
args = [objectArg, arrayArg, false, undefined, null, NaN, '', 0, 1.0];
|
||||
|
||||
callTracker.track({ object: {}, args });
|
||||
|
||||
expect(callTracker.mostRecent().args).toEqual(JSON.stringify(args));
|
||||
});
|
||||
|
||||
it('saves primitive arguments by value', function() {
|
||||
const callTracker = new jasmineUnderTest.CallTracker(),
|
||||
const callTracker = new privateUnderTest.CallTracker(),
|
||||
args = [undefined, null, false, '', /\s/, 0, 1.2, NaN];
|
||||
|
||||
callTracker.saveArgumentsByValue();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
describe('ClearStack', function() {
|
||||
it('works in an integrationy way', function(done) {
|
||||
const clearStack = jasmineUnderTest.getClearStack(
|
||||
const clearStack = privateUnderTest.getClearStack(
|
||||
jasmineUnderTest.getGlobal()
|
||||
);
|
||||
|
||||
@@ -9,160 +9,257 @@ describe('ClearStack', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('uses setImmediate when available', function() {
|
||||
const setImmediate = jasmine
|
||||
.createSpy('setImmediate')
|
||||
.and.callFake(function(fn) {
|
||||
fn();
|
||||
}),
|
||||
global = { setImmediate: setImmediate },
|
||||
clearStack = jasmineUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
describe('in Safari', function() {
|
||||
usesQueueMicrotaskWithSetTimeout(function() {
|
||||
return {
|
||||
navigator: {
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.0.8 (KHTML, like Gecko) Version/15.1 Safari/605.0.8'
|
||||
},
|
||||
// queueMicrotask should be used even though MessageChannel is present
|
||||
MessageChannel: fakeMessageChannel
|
||||
};
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
expect(setImmediate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('uses setTimeout instead of setImmediate every 10 calls to make sure we release the CPU', function() {
|
||||
const setImmediate = jasmine.createSpy('setImmediate'),
|
||||
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() {});
|
||||
|
||||
expect(setImmediate).toHaveBeenCalled();
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
|
||||
clearStack(function() {});
|
||||
expect(setImmediate.calls.count()).toEqual(9);
|
||||
expect(setTimeout.calls.count()).toEqual(1);
|
||||
|
||||
clearStack(function() {});
|
||||
expect(setImmediate.calls.count()).toEqual(10);
|
||||
expect(setTimeout.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('uses MessageChannels when available', function() {
|
||||
const fakeChannel = {
|
||||
port1: {},
|
||||
port2: {
|
||||
postMessage: function() {
|
||||
fakeChannel.port1.onmessage();
|
||||
}
|
||||
}
|
||||
},
|
||||
global = {
|
||||
MessageChannel: function() {
|
||||
return fakeChannel;
|
||||
}
|
||||
},
|
||||
clearStack = jasmineUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
|
||||
it('uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU', function() {
|
||||
const fakeChannel = {
|
||||
port1: {},
|
||||
port2: {
|
||||
postMessage: jasmine
|
||||
.createSpy('postMessage')
|
||||
.and.callFake(function() {
|
||||
fakeChannel.port1.onmessage();
|
||||
})
|
||||
}
|
||||
},
|
||||
setTimeout = jasmine.createSpy('setTimeout'),
|
||||
global = {
|
||||
it('uses MessageChannel to reduce setTimeout clamping', function() {
|
||||
const fakeChannel = fakeMessageChannel();
|
||||
spyOn(fakeChannel.port2, 'postMessage');
|
||||
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||
const global = {
|
||||
navigator: {
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.0.8 (KHTML, like Gecko) Version/15.1 Safari/605.0.8'
|
||||
},
|
||||
MessageChannel: function() {
|
||||
return fakeChannel;
|
||||
},
|
||||
setTimeout: setTimeout
|
||||
},
|
||||
clearStack = jasmineUnderTest.getClearStack(global);
|
||||
queueMicrotask
|
||||
};
|
||||
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
|
||||
expect(fakeChannel.port2.postMessage).toHaveBeenCalled();
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
for (let i = 0; i < 9; i++) {
|
||||
clearStack(function() {});
|
||||
}
|
||||
|
||||
clearStack(function() {});
|
||||
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(9);
|
||||
expect(setTimeout.calls.count()).toEqual(1);
|
||||
expect(fakeChannel.port2.postMessage).not.toHaveBeenCalled();
|
||||
|
||||
clearStack(function() {});
|
||||
expect(fakeChannel.port2.postMessage.calls.count()).toEqual(10);
|
||||
expect(setTimeout.calls.count()).toEqual(1);
|
||||
clearStack(function() {});
|
||||
|
||||
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('calls setTimeout when onmessage is called recursively', function() {
|
||||
const fakeChannel = {
|
||||
port1: {},
|
||||
port2: {
|
||||
postMessage: function() {
|
||||
fakeChannel.port1.onmessage();
|
||||
describe("in WebKit (Playwright's build for Windows)", function() {
|
||||
usesQueueMicrotaskWithSetTimeout(function() {
|
||||
return {
|
||||
navigator: {
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/605.1.15 (KHTML, like Gecko)'
|
||||
},
|
||||
// queueMicrotask should be used even though MessageChannel is present
|
||||
MessageChannel: fakeMessageChannel
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
describe('in browsers other than Safari', function() {
|
||||
usesMessageChannel(function() {
|
||||
return {
|
||||
navigator: {
|
||||
// Chrome's user agent string contains "Safari" so it's a good test case
|
||||
userAgent:
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
describe('when MessageChannel is unavailable', function() {
|
||||
usesQueueMicrotaskWithSetTimeout(function() {
|
||||
return {
|
||||
navigator: {
|
||||
userAgent: 'CERN-LineMode/2.15 libwww/2.17b3',
|
||||
MessageChannel: undefined
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('in Node', function() {
|
||||
usesQueueMicrotaskWithoutSetTimeout(function() {
|
||||
return {
|
||||
process: {
|
||||
versions: {
|
||||
node: '3.1415927'
|
||||
}
|
||||
}
|
||||
},
|
||||
setTimeout = jasmine.createSpy('setTimeout'),
|
||||
global = {
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
function usesMessageChannel(makeGlobal) {
|
||||
it('uses MessageChannel', function() {
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
MessageChannel: fakeMessageChannel
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
|
||||
it('uses setTimeout instead of MessageChannel every 10 calls to make sure we release the CPU', function() {
|
||||
const fakeChannel = fakeMessageChannel();
|
||||
spyOn(fakeChannel.port2, 'postMessage');
|
||||
const setTimeout = jasmine.createSpy('setTimeout');
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
setTimeout,
|
||||
MessageChannel: function() {
|
||||
return fakeChannel;
|
||||
},
|
||||
setTimeout: setTimeout
|
||||
},
|
||||
clearStack = jasmineUnderTest.getClearStack(global),
|
||||
fn = jasmine.createSpy('second clearStack function');
|
||||
}
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
|
||||
clearStack(function() {
|
||||
clearStack(fn);
|
||||
for (let i = 0; i < 9; i++) {
|
||||
clearStack(function() {});
|
||||
}
|
||||
|
||||
expect(fakeChannel.port2.postMessage).toHaveBeenCalled();
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
|
||||
clearStack(function() {});
|
||||
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(9);
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
|
||||
clearStack(function() {});
|
||||
expect(fakeChannel.port2.postMessage).toHaveBeenCalledTimes(10);
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
expect(setTimeout).toHaveBeenCalledWith(fn, 0);
|
||||
});
|
||||
it('calls setTimeout when onmessage is called recursively', function() {
|
||||
const setTimeout = jasmine.createSpy('setTimeout');
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
setTimeout,
|
||||
MessageChannel: fakeMessageChannel
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
const fn = jasmine.createSpy('second clearStack function');
|
||||
|
||||
it('falls back to setTimeout', function() {
|
||||
const setTimeout = jasmine
|
||||
.createSpy('setTimeout')
|
||||
.and.callFake(function(fn) {
|
||||
clearStack(function() {
|
||||
clearStack(fn);
|
||||
});
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
expect(setTimeout).toHaveBeenCalledWith(fn, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function usesQueueMicrotaskWithSetTimeout(makeGlobal) {
|
||||
it('uses queueMicrotask', function() {
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
queueMicrotask: function(fn) {
|
||||
fn();
|
||||
}),
|
||||
global = { setTimeout: setTimeout },
|
||||
clearStack = jasmineUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
}
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
expect(setTimeout).toHaveBeenCalledWith(jasmine.any(Function), 0);
|
||||
});
|
||||
it('uses setTimeout instead of queueMicrotask every 10 calls to make sure we release the CPU', function() {
|
||||
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||
const setTimeout = jasmine.createSpy('setTimeout');
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
queueMicrotask,
|
||||
setTimeout
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
|
||||
for (let i = 0; i < 9; i++) {
|
||||
clearStack(function() {});
|
||||
}
|
||||
|
||||
expect(queueMicrotask).toHaveBeenCalled();
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
|
||||
clearStack(function() {});
|
||||
expect(queueMicrotask).toHaveBeenCalledTimes(9);
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
|
||||
clearStack(function() {});
|
||||
expect(queueMicrotask).toHaveBeenCalledTimes(10);
|
||||
expect(setTimeout).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
}
|
||||
|
||||
function usesQueueMicrotaskWithoutSetTimeout(makeGlobal) {
|
||||
it('uses queueMicrotask', function() {
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
queueMicrotask: function(fn) {
|
||||
fn();
|
||||
}
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
let called = false;
|
||||
|
||||
clearStack(function() {
|
||||
called = true;
|
||||
});
|
||||
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
|
||||
it('does not use setTimeout', function() {
|
||||
const queueMicrotask = jasmine.createSpy('queueMicrotask');
|
||||
const setTimeout = jasmine.createSpy('setTimeout');
|
||||
const global = {
|
||||
...makeGlobal(),
|
||||
queueMicrotask,
|
||||
setTimeout
|
||||
};
|
||||
const clearStack = privateUnderTest.getClearStack(global);
|
||||
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
clearStack(function() {});
|
||||
|
||||
expect(queueMicrotask).toHaveBeenCalledTimes(10);
|
||||
expect(setTimeout).not.toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
|
||||
function fakeMessageChannel() {
|
||||
const channel = {
|
||||
port1: {},
|
||||
port2: {
|
||||
postMessage: function() {
|
||||
channel.port1.onmessage();
|
||||
}
|
||||
}
|
||||
};
|
||||
return channel;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -51,7 +51,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -88,7 +88,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -122,7 +122,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -154,7 +154,7 @@ describe('Clock', function() {
|
||||
'delayedFunctionSchedulerFactory'
|
||||
),
|
||||
mockDate = {},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
delayedFunctionSchedulerFactory,
|
||||
mockDate
|
||||
@@ -178,7 +178,7 @@ describe('Clock', function() {
|
||||
'delayedFunctionSchedulerFactory'
|
||||
),
|
||||
mockDate = {},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
delayedFunctionSchedulerFactory,
|
||||
mockDate
|
||||
@@ -202,7 +202,7 @@ describe('Clock', function() {
|
||||
'delayedFunctionSchedulerFactory'
|
||||
),
|
||||
mockDate = {},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
delayedFunctionSchedulerFactory,
|
||||
mockDate
|
||||
@@ -226,7 +226,7 @@ describe('Clock', function() {
|
||||
'delayedFunctionSchedulerFactory'
|
||||
),
|
||||
mockDate = {},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
delayedFunctionSchedulerFactory,
|
||||
mockDate
|
||||
@@ -242,7 +242,7 @@ describe('Clock', function() {
|
||||
expect(fakeGlobal.clearInterval).toBe(replacedClearInterval);
|
||||
});
|
||||
|
||||
it('replaces the global timer functions on uninstall', function() {
|
||||
it('restores the global timer functions on uninstall', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('global setTimeout'),
|
||||
fakeClearTimeout = jasmine.createSpy('global clearTimeout'),
|
||||
fakeSetInterval = jasmine.createSpy('global setInterval'),
|
||||
@@ -263,7 +263,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -306,7 +306,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -366,7 +366,7 @@ describe('Clock', function() {
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -408,215 +408,258 @@ describe('Clock', function() {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('schedules the delayed function (via setTimeout) with the fake timer', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
clock.install();
|
||||
clock.setTimeout(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetTimeout).not.toHaveBeenCalled();
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b']
|
||||
);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
false,
|
||||
timeout
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns an id for the delayed function', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine
|
||||
.createSpy('scheduleFunction')
|
||||
.and.returnValue(scheduleId),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
const timeout = clock.setTimeout(delayedFn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(timeout).toEqual(123);
|
||||
} else {
|
||||
expect(timeout.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
|
||||
it('clears the scheduled function with the scheduler', function() {
|
||||
const fakeClearTimeout = jasmine.createSpy('clearTimeout'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj(
|
||||
'delayedFunctionScheduler',
|
||||
['removeFunctionWithId']
|
||||
),
|
||||
fakeGlobal = { setTimeout: fakeClearTimeout },
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
clock.clearTimeout(123);
|
||||
|
||||
expect(fakeClearTimeout).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(
|
||||
123
|
||||
it('identifies its timing functions', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('global setTimeout');
|
||||
const fakeGlobal = { setTimeout: fakeSetTimeout };
|
||||
const delayedFunctionScheduler = jasmine.createSpyObj(
|
||||
'delayedFunctionScheduler',
|
||||
['scheduleFunction']
|
||||
);
|
||||
});
|
||||
|
||||
it('schedules the delayed function with the fake timer', function() {
|
||||
const fakeSetInterval = jasmine.createSpy('setInterval'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setInterval: fakeSetInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
const mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
};
|
||||
const clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
clock.install();
|
||||
clock.setInterval(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetInterval).not.toHaveBeenCalled();
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
true
|
||||
);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
true,
|
||||
timeout
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns an id for the delayed function', function() {
|
||||
const fakeSetInterval = jasmine.createSpy('setInterval'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine
|
||||
.createSpy('scheduleFunction')
|
||||
.and.returnValue(scheduleId),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setInterval: fakeSetInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
const interval = clock.setInterval(delayedFn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(interval).toEqual(123);
|
||||
} else {
|
||||
expect(interval.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
|
||||
it('clears the scheduled function with the scheduler', function() {
|
||||
const clearInterval = jasmine.createSpy('clearInterval'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj(
|
||||
'delayedFunctionScheduler',
|
||||
['removeFunctionWithId']
|
||||
),
|
||||
fakeGlobal = { setInterval: clearInterval },
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
clock.clearInterval(123);
|
||||
|
||||
expect(clearInterval).not.toHaveBeenCalled();
|
||||
expect(delayedFunctionScheduler.removeFunctionWithId).toHaveBeenCalledWith(
|
||||
123
|
||||
mockDate
|
||||
);
|
||||
clock.install();
|
||||
|
||||
expect(
|
||||
fakeGlobal.setTimeout[privateUnderTest.Clock.IsMockClockTimingFn]
|
||||
).toEqual(true);
|
||||
expect(
|
||||
fakeGlobal.clearTimeout[privateUnderTest.Clock.IsMockClockTimingFn]
|
||||
).toEqual(true);
|
||||
expect(
|
||||
fakeGlobal.setInterval[privateUnderTest.Clock.IsMockClockTimingFn]
|
||||
).toEqual(true);
|
||||
expect(
|
||||
fakeGlobal.clearInterval[privateUnderTest.Clock.IsMockClockTimingFn]
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
describe('setTimeout', function() {
|
||||
it('schedules the delayed function with the fake timer', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
clock.install();
|
||||
clock.setTimeout(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetTimeout).not.toHaveBeenCalled();
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b']
|
||||
);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
false,
|
||||
timeout
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns an id for the delayed function', function() {
|
||||
const fakeSetTimeout = jasmine.createSpy('setTimeout'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine
|
||||
.createSpy('scheduleFunction')
|
||||
.and.returnValue(scheduleId),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setTimeout: fakeSetTimeout },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
const timeout = clock.setTimeout(delayedFn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(timeout).toEqual(123);
|
||||
} else {
|
||||
expect(timeout.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearTimeout', function() {
|
||||
it('clears the scheduled function with the scheduler', function() {
|
||||
const fakeClearTimeout = jasmine.createSpy('clearTimeout'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj(
|
||||
'delayedFunctionScheduler',
|
||||
['removeFunctionWithId']
|
||||
),
|
||||
fakeGlobal = { setTimeout: fakeClearTimeout },
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
clock.clearTimeout(123);
|
||||
|
||||
expect(fakeClearTimeout).not.toHaveBeenCalled();
|
||||
expect(
|
||||
delayedFunctionScheduler.removeFunctionWithId
|
||||
).toHaveBeenCalledWith(123);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setInterval', function() {
|
||||
it('schedules the delayed function with the fake timer', function() {
|
||||
const fakeSetInterval = jasmine.createSpy('setInterval'),
|
||||
scheduleFunction = jasmine.createSpy('scheduleFunction'),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setInterval: fakeSetInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
),
|
||||
timeout = new clock.FakeTimeout();
|
||||
|
||||
clock.install();
|
||||
clock.setInterval(delayedFn, 0, 'a', 'b');
|
||||
|
||||
expect(fakeSetInterval).not.toHaveBeenCalled();
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
true
|
||||
);
|
||||
} else {
|
||||
expect(delayedFunctionScheduler.scheduleFunction).toHaveBeenCalledWith(
|
||||
delayedFn,
|
||||
0,
|
||||
['a', 'b'],
|
||||
true,
|
||||
timeout
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('returns an id for the delayed function', function() {
|
||||
const fakeSetInterval = jasmine.createSpy('setInterval'),
|
||||
scheduleId = 123,
|
||||
scheduleFunction = jasmine
|
||||
.createSpy('scheduleFunction')
|
||||
.and.returnValue(scheduleId),
|
||||
delayedFunctionScheduler = { scheduleFunction: scheduleFunction },
|
||||
fakeGlobal = { setInterval: fakeSetInterval },
|
||||
delayedFn = jasmine.createSpy('delayedFn'),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
const interval = clock.setInterval(delayedFn, 0);
|
||||
|
||||
if (!NODE_JS) {
|
||||
expect(interval).toEqual(123);
|
||||
} else {
|
||||
expect(interval.constructor.name).toEqual('FakeTimeout');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearInterval', function() {
|
||||
it('clears the scheduled function with the scheduler', function() {
|
||||
const clearInterval = jasmine.createSpy('clearInterval'),
|
||||
delayedFunctionScheduler = jasmine.createSpyObj(
|
||||
'delayedFunctionScheduler',
|
||||
['removeFunctionWithId']
|
||||
),
|
||||
fakeGlobal = { setInterval: clearInterval },
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new privateUnderTest.Clock(
|
||||
fakeGlobal,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
|
||||
clock.install();
|
||||
clock.clearInterval(123);
|
||||
|
||||
expect(clearInterval).not.toHaveBeenCalled();
|
||||
expect(
|
||||
delayedFunctionScheduler.removeFunctionWithId
|
||||
).toHaveBeenCalledWith(123);
|
||||
});
|
||||
});
|
||||
|
||||
it('gives you a friendly reminder if the Clock is not installed and you tick', function() {
|
||||
const clock = new jasmineUnderTest.Clock(
|
||||
const clock = new privateUnderTest.Clock(
|
||||
{},
|
||||
jasmine.createSpyObj('delayedFunctionScheduler', ['tick'])
|
||||
);
|
||||
@@ -632,13 +675,13 @@ describe('Clock (acceptance)', function() {
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFn3 = jasmine.createSpy('delayedFn3'),
|
||||
recurring1 = jasmine.createSpy('recurring1'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -687,15 +730,168 @@ describe('Clock (acceptance)', function() {
|
||||
expect(recurring1.calls.count()).toBe(4);
|
||||
});
|
||||
|
||||
describe('auto tick mode', () => {
|
||||
let delayedFunctionScheduler;
|
||||
let mockDate;
|
||||
let clock;
|
||||
|
||||
beforeEach(() => {
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
};
|
||||
// window setTimeout to window to make firefox happy
|
||||
const _setTimeout =
|
||||
typeof window !== 'undefined' ? setTimeout.bind(window) : setTimeout;
|
||||
// passing a fake global allows us to preserve the real timing functions for use in tests
|
||||
const _global = { setTimeout: _setTimeout, setInterval: setInterval };
|
||||
clock = new privateUnderTest.Clock(
|
||||
_global,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
},
|
||||
mockDate
|
||||
);
|
||||
clock.install().autoTick();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
clock.uninstall();
|
||||
});
|
||||
|
||||
it('flushes microtask queue between macrotasks', async () => {
|
||||
const log = [];
|
||||
await new Promise(r => clock.setTimeout(r, 10)).then(() => {
|
||||
log.push(1);
|
||||
Promise.resolve().then(() => log.push(2));
|
||||
Promise.resolve().then(() => log.push(3));
|
||||
});
|
||||
await new Promise(r => clock.setTimeout(r, 10)).then(() => {
|
||||
log.push(4);
|
||||
Promise.resolve().then(() => log.push(5));
|
||||
});
|
||||
expect(log).toEqual([1, 2, 3, 4, 5]);
|
||||
});
|
||||
|
||||
it('can run setTimeouts/setIntervals asynchronously', function() {
|
||||
const recurring = jasmine.createSpy('recurring'),
|
||||
fn1 = jasmine.createSpy('fn1'),
|
||||
fn2 = jasmine.createSpy('fn2'),
|
||||
fn3 = jasmine.createSpy('fn3');
|
||||
|
||||
const intervalId = clock.setInterval(recurring, 50);
|
||||
// In a microtask, add some timeouts.
|
||||
Promise.resolve()
|
||||
.then(function() {
|
||||
return new Promise(function(resolve) {
|
||||
clock.setTimeout(resolve, 25);
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
fn1();
|
||||
return new Promise(function(resolve) {
|
||||
clock.setTimeout(resolve, 200);
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
fn2();
|
||||
return new Promise(function(resolve) {
|
||||
clock.setTimeout(resolve, 100);
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
fn3();
|
||||
});
|
||||
|
||||
expect(recurring).not.toHaveBeenCalled();
|
||||
expect(fn1).not.toHaveBeenCalled();
|
||||
expect(fn2).not.toHaveBeenCalled();
|
||||
expect(fn3).not.toHaveBeenCalled();
|
||||
|
||||
return new Promise(resolve => clock.setTimeout(resolve, 50))
|
||||
.then(function() {
|
||||
expect(recurring).toHaveBeenCalledTimes(1);
|
||||
expect(fn1).toHaveBeenCalled();
|
||||
expect(fn2).not.toHaveBeenCalled();
|
||||
expect(fn3).not.toHaveBeenCalled();
|
||||
|
||||
return new Promise(resolve => clock.setTimeout(resolve, 175));
|
||||
})
|
||||
.then(function() {
|
||||
expect(recurring).toHaveBeenCalledTimes(4);
|
||||
expect(fn1).toHaveBeenCalled();
|
||||
expect(fn2).toHaveBeenCalled();
|
||||
expect(fn3).not.toHaveBeenCalled();
|
||||
|
||||
clock.clearInterval(intervalId);
|
||||
return new Promise(resolve => clock.setTimeout(resolve, 100));
|
||||
})
|
||||
.then(function() {
|
||||
expect(recurring).toHaveBeenCalledTimes(4);
|
||||
expect(fn1).toHaveBeenCalled();
|
||||
expect(fn2).toHaveBeenCalled();
|
||||
expect(fn3).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('aborts auto ticking when uninstalled, even if installed again synchonrously', async () => {
|
||||
clock.uninstall();
|
||||
clock.install();
|
||||
|
||||
let resolved = false;
|
||||
const promise = new Promise(resolve => {
|
||||
clock.setTimeout(resolve, 1);
|
||||
}).then(() => {
|
||||
resolved = true;
|
||||
});
|
||||
|
||||
// wait some real time and verify that the clock did not flush the timer above automatically
|
||||
await new Promise(resolve => setTimeout(resolve, 2));
|
||||
expect(resolved).toBe(false);
|
||||
|
||||
// enabling auto tick again will flush the timer
|
||||
clock.autoTick();
|
||||
await expectAsync(promise).toBeResolved();
|
||||
});
|
||||
|
||||
it('speeds up the execution of the timers in all browsers', async () => {
|
||||
const startTimeMs = performance.now() / 1000;
|
||||
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
||||
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
||||
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
||||
await new Promise(resolve => clock.setTimeout(resolve, 5000));
|
||||
const endTimeMs = performance.now() / 1000;
|
||||
// Ensure we didn't take 20s to complete the awaits above and, in fact, can do it in a fraction of a second
|
||||
expect(endTimeMs - startTimeMs).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it('is easy to test async functions with interleaved timers and microtasks', async () => {
|
||||
async function blackBoxWithLotsOfAsyncStuff() {
|
||||
await new Promise(r => clock.setTimeout(r, 10));
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
await new Promise(r => clock.setTimeout(r, 20));
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
return 'done';
|
||||
}
|
||||
const result = await blackBoxWithLotsOfAsyncStuff();
|
||||
expect(result).toBe('done');
|
||||
});
|
||||
});
|
||||
|
||||
it('can clear a previously set timeout', function() {
|
||||
const clearedFn = jasmine.createSpy('clearedFn'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -716,13 +912,13 @@ describe('Clock (acceptance)', function() {
|
||||
|
||||
it("can clear a previously set interval using that interval's handler", function() {
|
||||
const spy = jasmine.createSpy('spy'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setInterval: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -743,13 +939,13 @@ describe('Clock (acceptance)', function() {
|
||||
|
||||
it('correctly schedules functions after the Clock has advanced', function() {
|
||||
const delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -770,13 +966,13 @@ describe('Clock (acceptance)', function() {
|
||||
it('correctly schedules functions while the Clock is advancing', function() {
|
||||
const delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -801,13 +997,13 @@ describe('Clock (acceptance)', function() {
|
||||
it('correctly calls functions scheduled while the Clock is advancing', function() {
|
||||
const delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -829,13 +1025,13 @@ describe('Clock (acceptance)', function() {
|
||||
it('correctly schedules functions scheduled while the Clock is advancing but after the Clock is uninstalled', function() {
|
||||
const delayedFn1 = jasmine.createSpy('delayedFn1'),
|
||||
delayedFn2 = jasmine.createSpy('delayedFn2'),
|
||||
delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
mockDate = {
|
||||
install: function() {},
|
||||
tick: function() {},
|
||||
uninstall: function() {}
|
||||
},
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: function() {} },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -861,10 +1057,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('does not mock the Date object by default', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -884,10 +1080,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('mocks the Date object and sets it to current time', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -914,10 +1110,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('mocks the Date object and sets it to a given time', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -947,10 +1143,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('throws mockDate is called with a non-Date', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -965,10 +1161,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('mocks the Date object and updates the date per delayed function', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
{ setTimeout: setTimeout },
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -1004,10 +1200,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('correctly clears a scheduled timeout while the Clock is advancing', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date, setTimeout: undefined },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
global,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
@@ -1029,10 +1225,10 @@ describe('Clock (acceptance)', function() {
|
||||
});
|
||||
|
||||
it('correctly clears a scheduled interval while the Clock is advancing', function() {
|
||||
const delayedFunctionScheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const delayedFunctionScheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
global = { Date: Date, setTimeout: undefined },
|
||||
mockDate = new jasmineUnderTest.MockDate(global),
|
||||
clock = new jasmineUnderTest.Clock(
|
||||
mockDate = new privateUnderTest.MockDate(global),
|
||||
clock = new privateUnderTest.Clock(
|
||||
global,
|
||||
function() {
|
||||
return delayedFunctionScheduler;
|
||||
|
||||
@@ -2,7 +2,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
describe('#skipTo', function() {
|
||||
describe('Before anything has errored', function() {
|
||||
it('returns the next index', function() {
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
arrayOfArbitraryFns(4),
|
||||
4
|
||||
);
|
||||
@@ -15,7 +15,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
const fns = arrayOfArbitraryFns(4);
|
||||
fns[2].type = arbitraryCleanupType();
|
||||
fns[3].type = arbitraryCleanupType();
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(fns);
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(fns);
|
||||
|
||||
policy.fnErrored(0);
|
||||
expect(policy.skipTo(0)).toEqual(2);
|
||||
@@ -27,7 +27,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
it(`does not skip ${type} fns`, function() {
|
||||
const fns = arrayOfArbitraryFns(2);
|
||||
fns[1].type = type;
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
fns
|
||||
);
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
type: arbitraryCleanupType()
|
||||
}
|
||||
];
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
fns
|
||||
);
|
||||
|
||||
@@ -90,7 +90,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
type: arbitraryCleanupType()
|
||||
}
|
||||
];
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(
|
||||
fns
|
||||
);
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('CompleteOnFirstErrorSkipPolicy', function() {
|
||||
type: arbitraryCleanupType()
|
||||
}
|
||||
];
|
||||
const policy = new jasmineUnderTest.CompleteOnFirstErrorSkipPolicy(fns);
|
||||
const policy = new privateUnderTest.CompleteOnFirstErrorSkipPolicy(fns);
|
||||
|
||||
policy.fnErrored(0);
|
||||
expect(policy.skipTo(0)).toEqual(1);
|
||||
|
||||
113
spec/core/ConfigurationSpec.js
Normal file
113
spec/core/ConfigurationSpec.js
Normal file
@@ -0,0 +1,113 @@
|
||||
describe('Configuration', function() {
|
||||
const standardBooleanKeys = [
|
||||
'random',
|
||||
'stopOnSpecFailure',
|
||||
'stopSpecOnExpectationFailure',
|
||||
'failSpecWithNoExpectations',
|
||||
'hideDisabled',
|
||||
'autoCleanClosures',
|
||||
'forbidDuplicateNames',
|
||||
'detectLateRejectionHandling',
|
||||
'verboseDeprecations'
|
||||
];
|
||||
const allKeys = [...standardBooleanKeys, 'seed', 'specFilter'];
|
||||
Object.freeze(standardBooleanKeys);
|
||||
Object.freeze(allKeys);
|
||||
|
||||
it('provides defaults', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
expect(subject.random).toEqual(true);
|
||||
expect(subject.seed).toBeNull();
|
||||
expect(subject.stopOnSpecFailure).toEqual(false);
|
||||
expect(subject.stopSpecOnExpectationFailure).toEqual(false);
|
||||
expect(subject.failSpecWithNoExpectations).toEqual(false);
|
||||
expect(subject.specFilter).toEqual(jasmine.any(Function));
|
||||
expect(subject.specFilter()).toEqual(true);
|
||||
expect(subject.hideDisabled).toEqual(false);
|
||||
expect(subject.autoCleanClosures).toEqual(true);
|
||||
expect(subject.forbidDuplicateNames).toEqual(true);
|
||||
expect(subject.verboseDeprecations).toEqual(false);
|
||||
expect(subject.detectLateRejectionHandling).toEqual(false);
|
||||
});
|
||||
|
||||
describe('copy()', function() {
|
||||
it('returns a copy of the configuration as a plain old JS object', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
|
||||
const copy = subject.copy();
|
||||
|
||||
expect(copy.constructor.name).toEqual('Object');
|
||||
|
||||
expect(new Set(Object.keys(copy))).toEqual(new Set(allKeys));
|
||||
for (const k of allKeys) {
|
||||
expect(copy[k]).toEqual(subject[k]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('update()', function() {
|
||||
it('does not update properties that are absent from the parameter', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
const originalValues = subject.copy();
|
||||
|
||||
subject.update({});
|
||||
expect(subject.copy()).toEqual(originalValues);
|
||||
});
|
||||
|
||||
function booleanPropertyBehavior(key) {
|
||||
it('does not update the property if the specified value is undefined', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
const orig = subject[key];
|
||||
|
||||
subject.update({ [key]: undefined });
|
||||
|
||||
expect(subject[key]).toEqual(orig);
|
||||
});
|
||||
|
||||
it('updates the property if the specified value is not undefined', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
const orig = subject[key];
|
||||
|
||||
subject.update({ [key]: !orig });
|
||||
expect(subject[key]).toEqual(!orig);
|
||||
|
||||
subject.update({ [key]: orig });
|
||||
expect(subject[key]).toEqual(orig);
|
||||
});
|
||||
}
|
||||
|
||||
for (const k of standardBooleanKeys) {
|
||||
describe(k, function() {
|
||||
booleanPropertyBehavior(k);
|
||||
});
|
||||
}
|
||||
|
||||
it('sets specFilter when truthy', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
const orig = subject.specFilter;
|
||||
|
||||
subject.update({ specFilter: undefined });
|
||||
expect(subject.specFilter).toBe(orig);
|
||||
|
||||
subject.update({ specFilter: false });
|
||||
expect(subject.specFilter).toBe(orig);
|
||||
|
||||
function newSpecFilter() {}
|
||||
subject.update({ specFilter: newSpecFilter });
|
||||
expect(subject.specFilter).toBe(newSpecFilter);
|
||||
});
|
||||
|
||||
it('sets seed when not undefined', function() {
|
||||
const subject = new privateUnderTest.Configuration();
|
||||
|
||||
subject.update({ seed: undefined });
|
||||
expect(subject.seed).toBeNull();
|
||||
|
||||
subject.update({ seed: 1234 });
|
||||
expect(subject.seed).toEqual(1234);
|
||||
|
||||
subject.update({ seed: null });
|
||||
expect(subject.seed).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,8 @@
|
||||
describe('DelayedFunctionScheduler', function() {
|
||||
'use strict';
|
||||
|
||||
it('schedules a function for later execution', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0);
|
||||
@@ -12,19 +14,18 @@ describe('DelayedFunctionScheduler', function() {
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('schedules a string for later execution', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
strfn = 'horrible = true;';
|
||||
it('throws if a string is passed', function() {
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
|
||||
scheduler.scheduleFunction(strfn, 0);
|
||||
|
||||
scheduler.tick(0);
|
||||
|
||||
expect(horrible).toEqual(true);
|
||||
expect(function() {
|
||||
scheduler.scheduleFunction('horrible = true;', 0);
|
||||
}).toThrowError(
|
||||
'The mock clock does not support the eval form of setTimeout and setInterval. Pass a function instead of a string.'
|
||||
);
|
||||
});
|
||||
|
||||
it('#tick defaults to 0', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0);
|
||||
@@ -37,7 +38,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('defaults delay to 0', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn);
|
||||
@@ -50,7 +51,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('optionally passes params to scheduled functions', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 0, ['foo', 'bar']);
|
||||
@@ -63,7 +64,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('scheduled fns can optionally reoccur', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn');
|
||||
|
||||
scheduler.scheduleFunction(fn, 20, [], true);
|
||||
@@ -84,18 +85,19 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('increments scheduled fns ids unless one is passed', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler();
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(1);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(2);
|
||||
const initial = scheduler.scheduleFunction(function() {}, 0);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(initial + 1);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(initial + 2);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0, [], false, 123)).toBe(
|
||||
123
|
||||
);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(3);
|
||||
expect(scheduler.scheduleFunction(function() {}, 0)).toBe(initial + 3);
|
||||
});
|
||||
|
||||
it('#removeFunctionWithId removes a previously scheduled function with a given id', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
timeoutKey = scheduler.scheduleFunction(fn, 0);
|
||||
|
||||
@@ -109,7 +111,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('executes recurring functions interleaved with regular functions in the correct order', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler();
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
const fn = jasmine.createSpy('fn');
|
||||
let recurringCallCount = 0;
|
||||
const recurring = jasmine.createSpy('recurring').and.callFake(function() {
|
||||
@@ -130,7 +132,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('schedules a function for later execution during a tick', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
|
||||
@@ -146,7 +148,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('#removeFunctionWithId removes a previously scheduled function with a given id during a tick', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
let timeoutKey;
|
||||
@@ -164,7 +166,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('executes recurring functions interleaved with regular functions and functions scheduled during a tick in the correct order', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler();
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
const fn = jasmine.createSpy('fn');
|
||||
let recurringCallCount = 0;
|
||||
const recurring = jasmine.createSpy('recurring').and.callFake(function() {
|
||||
@@ -197,7 +199,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('executes recurring functions after rescheduling them', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
recurring = function() {
|
||||
expect(scheduler.scheduleFunction).toHaveBeenCalled();
|
||||
};
|
||||
@@ -210,7 +212,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('removes functions during a tick that runs the function', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
spy = jasmine.createSpy('fn'),
|
||||
spyAndRemove = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
@@ -231,7 +233,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it('removes functions during the first tick that runs the function', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
let timeoutKey;
|
||||
@@ -250,7 +252,7 @@ describe('DelayedFunctionScheduler', function() {
|
||||
});
|
||||
|
||||
it("does not remove a function that hasn't been added yet", function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
fn = jasmine.createSpy('fn'),
|
||||
fnDelay = 10;
|
||||
|
||||
@@ -264,8 +266,44 @@ describe('DelayedFunctionScheduler', function() {
|
||||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('runs the next scheduled funtion', function() {
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
const fn = jasmine.createSpy('fn');
|
||||
const tickSpy = jasmine.createSpy('tick');
|
||||
|
||||
scheduler.scheduleFunction(fn, 10, [], false, 'foo');
|
||||
|
||||
expect(fn).not.toHaveBeenCalled();
|
||||
|
||||
scheduler.runNextQueuedFunction(tickSpy);
|
||||
|
||||
expect(fn).toHaveBeenCalled();
|
||||
expect(tickSpy).toHaveBeenCalledWith(10);
|
||||
});
|
||||
|
||||
it('runs the only a single scheduled funtion in a time slot', function() {
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
const fn1 = jasmine.createSpy('fn');
|
||||
const fn2 = jasmine.createSpy('fn2');
|
||||
const tickSpy = jasmine.createSpy('tick');
|
||||
|
||||
scheduler.scheduleFunction(fn1, 10, [], false, 'foo1');
|
||||
scheduler.scheduleFunction(fn2, 10, [], false, 'foo2');
|
||||
|
||||
scheduler.runNextQueuedFunction(tickSpy);
|
||||
|
||||
expect(fn1).toHaveBeenCalled();
|
||||
expect(fn2).not.toHaveBeenCalled();
|
||||
expect(tickSpy).toHaveBeenCalledWith(10);
|
||||
|
||||
tickSpy.calls.reset();
|
||||
scheduler.runNextQueuedFunction(tickSpy);
|
||||
expect(fn2).toHaveBeenCalled();
|
||||
expect(tickSpy).toHaveBeenCalledWith(0);
|
||||
});
|
||||
|
||||
it('updates the mockDate per scheduled time', function() {
|
||||
const scheduler = new jasmineUnderTest.DelayedFunctionScheduler(),
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler(),
|
||||
tickDate = jasmine.createSpy('tickDate');
|
||||
|
||||
scheduler.scheduleFunction(function() {});
|
||||
@@ -277,6 +315,28 @@ describe('DelayedFunctionScheduler', function() {
|
||||
expect(tickDate).toHaveBeenCalledWith(1);
|
||||
});
|
||||
|
||||
it('does not conflict with native timer IDs', function() {
|
||||
const NODE_JS =
|
||||
typeof process !== 'undefined' &&
|
||||
process.versions &&
|
||||
typeof process.versions.node === 'string';
|
||||
if (NODE_JS) {
|
||||
pending('numeric timer ID conflicts only relevant for browsers.');
|
||||
}
|
||||
const nativeTimeoutId = setTimeout(function() {}, 100);
|
||||
|
||||
const scheduler = new privateUnderTest.DelayedFunctionScheduler();
|
||||
const fn = jasmine.createSpy('fn');
|
||||
|
||||
for (let i = 0; i < nativeTimeoutId; i++) {
|
||||
scheduler.scheduleFunction(fn, 0, [], false);
|
||||
}
|
||||
scheduler.removeFunctionWithId(nativeTimeoutId);
|
||||
scheduler.tick(1);
|
||||
|
||||
expect(fn).toHaveBeenCalledTimes(nativeTimeoutId);
|
||||
});
|
||||
|
||||
describe('ticking inside a scheduled function', function() {
|
||||
let clock;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('Deprecator', function() {
|
||||
|
||||
it('logs the mesage without context when the runnable is the top suite', function() {
|
||||
const runnable = { addDeprecationWarning: function() {} };
|
||||
const deprecator = new jasmineUnderTest.Deprecator(runnable);
|
||||
const deprecator = new privateUnderTest.Deprecator(runnable);
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
@@ -25,7 +25,7 @@ describe('Deprecator', function() {
|
||||
},
|
||||
children: []
|
||||
};
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
@@ -44,7 +44,7 @@ describe('Deprecator', function() {
|
||||
return 'the spec';
|
||||
}
|
||||
};
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
deprecator.verboseDeprecations(true);
|
||||
|
||||
deprecator.addDeprecationWarning(runnable, 'the message', {
|
||||
@@ -61,7 +61,7 @@ describe('Deprecator', function() {
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
]);
|
||||
const deprecator = new jasmineUnderTest.Deprecator(topSuite);
|
||||
const deprecator = new privateUnderTest.Deprecator(topSuite);
|
||||
const runnable = jasmine.createSpyObj('spec', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -105,7 +105,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('emits the deprecation only once when verboseDeprecations is not set', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -124,7 +124,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('emits the deprecation only once when verboseDeprecations is false', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -144,7 +144,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('emits the deprecation for each call when verboseDeprecations is true', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable1 = jasmine.createSpyObj('runnable1', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -164,7 +164,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('includes a note about verboseDeprecations', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -183,7 +183,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('omits the note about verboseDeprecations when verboseDeprecations is true', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -207,7 +207,7 @@ describe('Deprecator', function() {
|
||||
// to report their own deprecations through Jasmine. See
|
||||
// <https://github.com/jasmine/jasmine/pull/1498>.
|
||||
it('passes the error through unchanged', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -238,7 +238,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('reports the deprecation every time, regardless of config.verboseDeprecations', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -259,7 +259,7 @@ describe('Deprecator', function() {
|
||||
});
|
||||
|
||||
it('omits the note about verboseDeprecations', function() {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -293,7 +293,7 @@ describe('Deprecator', function() {
|
||||
}
|
||||
|
||||
function testStackTrace(options) {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
@@ -311,7 +311,7 @@ describe('Deprecator', function() {
|
||||
}
|
||||
|
||||
function testNoStackTrace(options) {
|
||||
const deprecator = new jasmineUnderTest.Deprecator({});
|
||||
const deprecator = new privateUnderTest.Deprecator({});
|
||||
const runnable = jasmine.createSpyObj('runnable', [
|
||||
'addDeprecationWarning',
|
||||
'getFullName'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
describe('Env', function() {
|
||||
let env;
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env = new privateUnderTest.Env();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -13,14 +13,14 @@ describe('Env', function() {
|
||||
it('throws the Pending Spec exception', function() {
|
||||
expect(function() {
|
||||
env.pending();
|
||||
}).toThrow(jasmineUnderTest.Spec.pendingSpecExceptionMessage);
|
||||
}).toThrow(privateUnderTest.Spec.pendingSpecExceptionMessage);
|
||||
});
|
||||
|
||||
it('throws the Pending Spec exception with a custom message', function() {
|
||||
expect(function() {
|
||||
env.pending('custom message');
|
||||
}).toThrow(
|
||||
jasmineUnderTest.Spec.pendingSpecExceptionMessage + 'custom message'
|
||||
privateUnderTest.Spec.pendingSpecExceptionMessage + 'custom message'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -38,24 +38,24 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
const suite = env.topSuite();
|
||||
expect(suite).not.toBeInstanceOf(jasmineUnderTest.Suite);
|
||||
expect(suite).not.toBeInstanceOf(privateUnderTest.Suite);
|
||||
expect(suite.description).toEqual('Jasmine__TopLevel__Suite');
|
||||
expect(suite.getFullName()).toEqual('');
|
||||
expect(suite.children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[0]).not.toBeInstanceOf(jasmineUnderTest.Spec);
|
||||
expect(suite.children[0]).not.toBeInstanceOf(privateUnderTest.Spec);
|
||||
expect(suite.children[0].description).toEqual('a top level spec');
|
||||
expect(suite.children[0].getFullName()).toEqual('a top level spec');
|
||||
expect(suite.children[0].children).toBeFalsy();
|
||||
|
||||
expect(suite.children[1]).not.toBeInstanceOf(jasmineUnderTest.Suite);
|
||||
expect(suite.children[1]).not.toBeInstanceOf(privateUnderTest.Suite);
|
||||
expect(suite.children[1].description).toEqual('a suite');
|
||||
expect(suite.children[1].getFullName()).toEqual('a suite');
|
||||
expect(suite.children[1].parentSuite).toBe(suite);
|
||||
expect(suite.children[1].children.length).toEqual(2);
|
||||
|
||||
expect(suite.children[1].children[0]).not.toBeInstanceOf(
|
||||
jasmineUnderTest.Spec
|
||||
privateUnderTest.Spec
|
||||
);
|
||||
expect(suite.children[1].children[0].description).toEqual('a spec');
|
||||
expect(suite.children[1].children[0].getFullName()).toEqual(
|
||||
@@ -80,6 +80,19 @@ describe('Env', function() {
|
||||
);
|
||||
expect(suite.children[1].children[1].children[0].children).toBeFalsy();
|
||||
});
|
||||
|
||||
it('throws if called in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
check();
|
||||
env.setParallelLoadingState('specs');
|
||||
check();
|
||||
|
||||
function check() {
|
||||
expect(function() {
|
||||
env.topSuite();
|
||||
}).toThrowError("'topSuite' is not available in parallel mode");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts its own current configureation', function() {
|
||||
@@ -89,9 +102,9 @@ describe('Env', function() {
|
||||
it('can configure specs to throw errors on expectation failures', function() {
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
spyOn(jasmineUnderTest, 'Spec').and.callThrough();
|
||||
spyOn(privateUnderTest, 'Spec').and.callThrough();
|
||||
env.it('foo', function() {});
|
||||
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
|
||||
expect(privateUnderTest.Spec).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
throwOnExpectationFailure: true
|
||||
})
|
||||
@@ -101,9 +114,9 @@ describe('Env', function() {
|
||||
it('can configure suites to throw errors on expectation failures', function() {
|
||||
env.configure({ stopSpecOnExpectationFailure: true });
|
||||
|
||||
spyOn(jasmineUnderTest, 'Suite');
|
||||
spyOn(privateUnderTest, 'Suite');
|
||||
env.describe('foo', function() {});
|
||||
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(
|
||||
expect(privateUnderTest.Suite).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
throwOnExpectationFailure: true
|
||||
})
|
||||
@@ -137,9 +150,9 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('defaults to multiple failures for specs', function() {
|
||||
spyOn(jasmineUnderTest, 'Spec').and.callThrough();
|
||||
spyOn(privateUnderTest, 'Spec').and.callThrough();
|
||||
env.it('bar', function() {});
|
||||
expect(jasmineUnderTest.Spec).toHaveBeenCalledWith(
|
||||
expect(privateUnderTest.Spec).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
throwOnExpectationFailure: false
|
||||
})
|
||||
@@ -147,9 +160,9 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('defaults to multiple failures for suites', function() {
|
||||
spyOn(jasmineUnderTest, 'Suite');
|
||||
spyOn(privateUnderTest, 'Suite');
|
||||
env.describe('foo', function() {});
|
||||
expect(jasmineUnderTest.Suite).toHaveBeenCalledWith(
|
||||
expect(privateUnderTest.Suite).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
throwOnExpectationFailure: false
|
||||
})
|
||||
@@ -192,7 +205,6 @@ describe('Env', function() {
|
||||
|
||||
it('throws an error when given arguments', function() {
|
||||
expect(function() {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
env.describe('done method', function(done) {});
|
||||
}).toThrowError('describe does not expect any arguments');
|
||||
});
|
||||
@@ -251,6 +263,15 @@ describe('Env', function() {
|
||||
|
||||
describe('#fdescribe', function() {
|
||||
behavesLikeDescribe('fdescribe');
|
||||
|
||||
it('throws an error in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.fdescribe('a suite', function() {
|
||||
env.it('a spec');
|
||||
});
|
||||
}).toThrowError("'fdescribe' is not available in parallel mode");
|
||||
});
|
||||
});
|
||||
|
||||
describe('xdescribe', function() {
|
||||
@@ -316,7 +337,7 @@ describe('Env', function() {
|
||||
|
||||
it('calls spec.exclude with "Temporarily disabled with xit"', function() {
|
||||
const excludeSpy = jasmine.createSpy();
|
||||
spyOn(env, 'it_').and.returnValue({
|
||||
spyOn(privateUnderTest.SuiteBuilder.prototype, 'it_').and.returnValue({
|
||||
exclude: excludeSpy
|
||||
});
|
||||
env.xit('foo', function() {});
|
||||
@@ -325,9 +346,9 @@ describe('Env', function() {
|
||||
|
||||
it('calls spec.pend with "Temporarily disabled with xit"', function() {
|
||||
const pendSpy = jasmine.createSpy();
|
||||
const realExclude = jasmineUnderTest.Spec.prototype.exclude;
|
||||
const realExclude = privateUnderTest.Spec.prototype.exclude;
|
||||
|
||||
spyOn(env, 'it_').and.returnValue({
|
||||
spyOn(privateUnderTest.SuiteBuilder.prototype, 'it_').and.returnValue({
|
||||
exclude: realExclude,
|
||||
pend: pendSpy
|
||||
});
|
||||
@@ -372,6 +393,13 @@ describe('Env', function() {
|
||||
env.fit('huge timeout', function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
|
||||
it('throws an error in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.fit('a spec', function() {});
|
||||
}).toThrowError("'fit' is not available in parallel mode");
|
||||
});
|
||||
});
|
||||
|
||||
describe('#beforeEach', function() {
|
||||
@@ -394,6 +422,28 @@ describe('Env', function() {
|
||||
env.beforeEach(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
|
||||
it('throws when called at the top level in a spec file in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.beforeEach(function() {});
|
||||
}).toThrowError(
|
||||
'In parallel mode, beforeEach must be in a describe block or in a helper file'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not throw when called at the top level in a helper file in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
env.beforeEach(function() {});
|
||||
});
|
||||
|
||||
it('does not throw when called in a describe in a spec file in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
env.describe('a suite', function() {
|
||||
env.beforeEach(function() {});
|
||||
env.it('a spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#beforeAll', function() {
|
||||
@@ -416,6 +466,47 @@ describe('Env', function() {
|
||||
env.beforeAll(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
|
||||
describe('in parallel mode', function() {
|
||||
it('throws an error when called at the top level', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
check();
|
||||
env.setParallelLoadingState('specs');
|
||||
check();
|
||||
|
||||
function check() {
|
||||
expect(function() {
|
||||
env.beforeAll(function() {});
|
||||
}).toThrowError(
|
||||
"In parallel mode, 'beforeAll' must be in a describe block. " +
|
||||
'Use the globalSetup config property for exactly-once setup in' +
|
||||
' parallel mode.'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not throw an error when called in a describe', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
check(1);
|
||||
env.setParallelLoadingState('specs');
|
||||
check(2);
|
||||
|
||||
function check(disambiguator) {
|
||||
let done = false;
|
||||
|
||||
env.describe('a suite ' + disambiguator, function() {
|
||||
expect(function() {
|
||||
env.it('a spec');
|
||||
env.beforeAll(function() {});
|
||||
}).not.toThrow();
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
expect(done).toBeTrue();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#afterEach', function() {
|
||||
@@ -438,6 +529,28 @@ describe('Env', function() {
|
||||
env.afterEach(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
|
||||
it('throws when called at the top level in a spec file in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.afterEach(function() {});
|
||||
}).toThrowError(
|
||||
'In parallel mode, afterEach must be in a describe block or in a helper file'
|
||||
);
|
||||
});
|
||||
|
||||
it('does not throw when called at the top level in a helper file in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
env.afterEach(function() {});
|
||||
});
|
||||
|
||||
it('does not throw when called in a describe in a spec file in parallel mode', function() {
|
||||
env.setParallelLoadingState('specs');
|
||||
env.describe('a suite', function() {
|
||||
env.afterEach(function() {});
|
||||
env.it('a spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#afterAll', function() {
|
||||
@@ -460,6 +573,47 @@ describe('Env', function() {
|
||||
env.afterAll(function() {}, 2147483648);
|
||||
}).toThrowError('Timeout value cannot be greater than 2147483647');
|
||||
});
|
||||
|
||||
describe('in parallel mode', function() {
|
||||
it('throws an error when called at the top level', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
check();
|
||||
env.setParallelLoadingState('specs');
|
||||
check();
|
||||
|
||||
function check() {
|
||||
expect(function() {
|
||||
env.afterAll(function() {});
|
||||
}).toThrowError(
|
||||
"In parallel mode, 'afterAll' must be in a describe block. " +
|
||||
'Use the globalTeardown config property for exactly-once ' +
|
||||
'teardown in parallel mode.'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('does not throw an error when called in a describe', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
check(1);
|
||||
env.setParallelLoadingState('specs');
|
||||
check(2);
|
||||
|
||||
function check(disambiguator) {
|
||||
let done = false;
|
||||
|
||||
env.describe('a suite ' + disambiguator, function() {
|
||||
expect(function() {
|
||||
env.it('a spec');
|
||||
env.afterAll(function() {});
|
||||
}).not.toThrow();
|
||||
|
||||
done = true;
|
||||
});
|
||||
|
||||
expect(done).toBeTrue();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when not constructed with suppressLoadErrors: true', function() {
|
||||
@@ -468,11 +622,15 @@ describe('Env', function() {
|
||||
'install',
|
||||
'uninstall',
|
||||
'pushListener',
|
||||
'popListener'
|
||||
'popListener',
|
||||
'removeOverrideListener'
|
||||
]);
|
||||
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
|
||||
env.cleanup_();
|
||||
env = new jasmineUnderTest.Env();
|
||||
env = new privateUnderTest.Env({
|
||||
GlobalErrors: function() {
|
||||
return globalErrors;
|
||||
}
|
||||
});
|
||||
expect(globalErrors.install).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -483,27 +641,32 @@ describe('Env', function() {
|
||||
'install',
|
||||
'uninstall',
|
||||
'pushListener',
|
||||
'popListener'
|
||||
'popListener',
|
||||
'removeOverrideListener'
|
||||
]);
|
||||
spyOn(jasmineUnderTest, 'GlobalErrors').and.returnValue(globalErrors);
|
||||
env.cleanup_();
|
||||
env = new jasmineUnderTest.Env({ suppressLoadErrors: true });
|
||||
env = new privateUnderTest.Env({
|
||||
suppressLoadErrors: true,
|
||||
GlobalErrors: function() {
|
||||
return globalErrors;
|
||||
}
|
||||
});
|
||||
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) {
|
||||
it('creates an expectationFactory that uses the current custom equality testers and object formatters', async function() {
|
||||
function customEqualityTester() {}
|
||||
function customObjectFormatter() {}
|
||||
function prettyPrinter() {}
|
||||
const RealSpec = jasmineUnderTest.Spec;
|
||||
const RealSpec = privateUnderTest.Spec;
|
||||
let specInstance;
|
||||
let expectationFactory;
|
||||
spyOn(jasmineUnderTest, 'MatchersUtil');
|
||||
spyOn(jasmineUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
|
||||
spyOn(jasmineUnderTest, 'Spec').and.callFake(function(options) {
|
||||
spyOn(privateUnderTest, 'MatchersUtil');
|
||||
spyOn(privateUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
|
||||
spyOn(privateUnderTest, 'Spec').and.callFake(function(options) {
|
||||
expectationFactory = options.expectationFactory;
|
||||
specInstance = new RealSpec(options);
|
||||
return specInstance;
|
||||
@@ -515,28 +678,26 @@ describe('Env', function() {
|
||||
expectationFactory('actual', specInstance);
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
|
||||
customObjectFormatter
|
||||
]);
|
||||
expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({
|
||||
customTesters: [customEqualityTester],
|
||||
pp: prettyPrinter
|
||||
});
|
||||
done();
|
||||
await env.execute();
|
||||
expect(privateUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
|
||||
customObjectFormatter
|
||||
]);
|
||||
expect(privateUnderTest.MatchersUtil).toHaveBeenCalledWith({
|
||||
customTesters: [customEqualityTester],
|
||||
pp: prettyPrinter
|
||||
});
|
||||
});
|
||||
|
||||
it('creates an asyncExpectationFactory that uses the current custom equality testers and object formatters', function(done) {
|
||||
it('creates an asyncExpectationFactory that uses the current custom equality testers and object formatters', async function() {
|
||||
function customEqualityTester() {}
|
||||
function customObjectFormatter() {}
|
||||
function prettyPrinter() {}
|
||||
const RealSpec = jasmineUnderTest.Spec;
|
||||
const RealSpec = privateUnderTest.Spec;
|
||||
let specInstance;
|
||||
let asyncExpectationFactory;
|
||||
spyOn(jasmineUnderTest, 'MatchersUtil');
|
||||
spyOn(jasmineUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
|
||||
spyOn(jasmineUnderTest, 'Spec').and.callFake(function(options) {
|
||||
spyOn(privateUnderTest, 'MatchersUtil');
|
||||
spyOn(privateUnderTest, 'makePrettyPrinter').and.returnValue(prettyPrinter);
|
||||
spyOn(privateUnderTest, 'Spec').and.callFake(function(options) {
|
||||
asyncExpectationFactory = options.asyncExpectationFactory;
|
||||
specInstance = new RealSpec(options);
|
||||
return specInstance;
|
||||
@@ -548,15 +709,14 @@ describe('Env', function() {
|
||||
asyncExpectationFactory('actual', specInstance);
|
||||
});
|
||||
|
||||
env.execute(null, function() {
|
||||
expect(jasmineUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
|
||||
customObjectFormatter
|
||||
]);
|
||||
expect(jasmineUnderTest.MatchersUtil).toHaveBeenCalledWith({
|
||||
customTesters: [customEqualityTester],
|
||||
pp: prettyPrinter
|
||||
});
|
||||
done();
|
||||
await env.execute();
|
||||
|
||||
expect(privateUnderTest.makePrettyPrinter).toHaveBeenCalledWith([
|
||||
customObjectFormatter
|
||||
]);
|
||||
expect(privateUnderTest.MatchersUtil).toHaveBeenCalledWith({
|
||||
customTesters: [customEqualityTester],
|
||||
pp: prettyPrinter
|
||||
});
|
||||
});
|
||||
|
||||
@@ -569,7 +729,7 @@ describe('Env', function() {
|
||||
env.it('has a spec');
|
||||
});
|
||||
|
||||
expect(suiteThis).not.toBeInstanceOf(jasmineUnderTest.Suite);
|
||||
expect(suiteThis).not.toBeInstanceOf(privateUnderTest.Suite);
|
||||
});
|
||||
|
||||
describe('#execute', function() {
|
||||
@@ -578,7 +738,7 @@ describe('Env', function() {
|
||||
});
|
||||
|
||||
it('should reset the topSuite when run twice', function() {
|
||||
spyOn(jasmineUnderTest.Suite.prototype, 'reset');
|
||||
spyOn(privateUnderTest.Suite.prototype, 'reset');
|
||||
return env
|
||||
.execute() // 1
|
||||
.then(function() {
|
||||
@@ -586,12 +746,95 @@ describe('Env', function() {
|
||||
})
|
||||
.then(function() {
|
||||
expect(
|
||||
jasmineUnderTest.Suite.prototype.reset
|
||||
privateUnderTest.Suite.prototype.reset
|
||||
).toHaveBeenCalledOnceWith();
|
||||
const id = jasmineUnderTest.Suite.prototype.reset.calls.thisFor(0).id;
|
||||
const id = privateUnderTest.Suite.prototype.reset.calls.thisFor(0).id;
|
||||
expect(id).toBeTruthy();
|
||||
expect(id).toEqual(env.topSuite().id);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not reset the topSuite if parallelReset was called since the last run', async function() {
|
||||
await env.execute();
|
||||
env.parallelReset();
|
||||
spyOn(privateUnderTest.Suite.prototype, 'reset');
|
||||
await env.execute();
|
||||
expect(privateUnderTest.Suite.prototype.reset).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('In parallel mode', function() {
|
||||
it('rejects if random is set to false', async function() {
|
||||
env.configure({ random: false });
|
||||
env.setParallelLoadingState('specs');
|
||||
await expectAsync(env.execute()).toBeRejectedWithError(
|
||||
'Randomization cannot be disabled in parallel mode'
|
||||
);
|
||||
});
|
||||
|
||||
it('rejects if seed is set', async function() {
|
||||
env.configure({ seed: 1234 });
|
||||
env.setParallelLoadingState('specs');
|
||||
await expectAsync(env.execute()).toBeRejectedWithError(
|
||||
'Random seed cannot be set in parallel mode'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#spyOnGlobalErrorsAsync', function() {
|
||||
it('throws if the callback does not return a promise', async function() {
|
||||
const msg =
|
||||
'The callback to spyOnGlobalErrorsAsync must be an async or ' +
|
||||
'promise-returning function';
|
||||
|
||||
await expectAsync(
|
||||
env.spyOnGlobalErrorsAsync(() => undefined)
|
||||
).toBeRejectedWithError(msg);
|
||||
await expectAsync(
|
||||
env.spyOnGlobalErrorsAsync(() => 'not a promise')
|
||||
).toBeRejectedWithError(msg);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#addReporter', function() {
|
||||
it('throws when called in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
expect(function() {
|
||||
env.addReporter({});
|
||||
}).toThrowError('Reporters cannot be added via Env in parallel mode');
|
||||
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.addReporter({});
|
||||
}).toThrowError('Reporters cannot be added via Env in parallel mode');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearReporters', function() {
|
||||
it('throws when called in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
expect(function() {
|
||||
env.clearReporters();
|
||||
}).toThrowError('Reporters cannot be removed via Env in parallel mode');
|
||||
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.clearReporters();
|
||||
}).toThrowError('Reporters cannot be removed via Env in parallel mode');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#configure', function() {
|
||||
it('throws when called in parallel mode', function() {
|
||||
env.setParallelLoadingState('helpers');
|
||||
expect(function() {
|
||||
env.configure({});
|
||||
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||
|
||||
env.setParallelLoadingState('specs');
|
||||
expect(function() {
|
||||
env.configure({});
|
||||
}).toThrowError('Jasmine cannot be configured via Env in parallel mode');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ describe('ExceptionFormatter', function() {
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleFirefoxException);
|
||||
|
||||
expect(message).toEqual(
|
||||
@@ -22,7 +22,7 @@ describe('ExceptionFormatter', function() {
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleWebkitException);
|
||||
|
||||
expect(message).toEqual(
|
||||
@@ -35,7 +35,7 @@ describe('ExceptionFormatter', function() {
|
||||
message: 'you got your foo in my bar',
|
||||
name: 'A Classic Mistake'
|
||||
},
|
||||
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(sampleV8);
|
||||
|
||||
expect(message).toEqual('A Classic Mistake: you got your foo in my bar');
|
||||
@@ -44,7 +44,7 @@ describe('ExceptionFormatter', function() {
|
||||
it('formats unnamed exceptions with message', function() {
|
||||
const unnamedError = { message: 'This is an unnamed error message.' };
|
||||
|
||||
const exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
const exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(unnamedError);
|
||||
|
||||
expect(message).toEqual('This is an unnamed error message.');
|
||||
@@ -57,7 +57,7 @@ describe('ExceptionFormatter', function() {
|
||||
};
|
||||
const emptyError = new EmptyError();
|
||||
|
||||
const exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
const exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(emptyError);
|
||||
|
||||
expect(message).toEqual('[EmptyError] thrown');
|
||||
@@ -65,7 +65,7 @@ describe('ExceptionFormatter', function() {
|
||||
|
||||
it("formats thrown exceptions that aren't errors", function() {
|
||||
const thrown = 'crazy error',
|
||||
exceptionFormatter = new jasmineUnderTest.ExceptionFormatter(),
|
||||
exceptionFormatter = new privateUnderTest.ExceptionFormatter(),
|
||||
message = exceptionFormatter.message(thrown);
|
||||
|
||||
expect(message).toEqual('crazy error thrown');
|
||||
@@ -76,7 +76,7 @@ describe('ExceptionFormatter', function() {
|
||||
it('formats stack traces', function() {
|
||||
const error = new Error('an error');
|
||||
|
||||
expect(new jasmineUnderTest.ExceptionFormatter().stack(error)).toMatch(
|
||||
expect(new privateUnderTest.ExceptionFormatter().stack(error)).toMatch(
|
||||
/ExceptionFormatterSpec\.js.*\d+/
|
||||
);
|
||||
});
|
||||
@@ -96,7 +96,7 @@ describe('ExceptionFormatter', function() {
|
||||
' at fn3 (C:\\__jasmine__\\lib\\jasmine-core\\jasmine.js:7575:25)\n' +
|
||||
' at fn4 (node:internal/timers:462:21)\n'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'C:\\__jasmine__\\lib\\jasmine-core\\jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
@@ -122,7 +122,7 @@ describe('ExceptionFormatter', function() {
|
||||
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
@@ -142,7 +142,26 @@ describe('ExceptionFormatter', function() {
|
||||
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const 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 with Firefox async annotations', function() {
|
||||
const error = {
|
||||
stack:
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'promise callback*fn1@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'setTimeout handler*fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
};
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
@@ -155,10 +174,12 @@ describe('ExceptionFormatter', function() {
|
||||
|
||||
it('filters Jasmine stack frames in this environment', function() {
|
||||
const error = new Error('an error');
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.util.jasmineFile()
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.private.util.jasmineFile()
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
jasmine.debugLog('Original stack trace: ' + error.stack);
|
||||
jasmine.debugLog('Filtered stack trace: ' + result);
|
||||
const lines = result.split('\n');
|
||||
|
||||
if (lines[0].match(/an error/)) {
|
||||
@@ -181,8 +202,8 @@ describe('ExceptionFormatter', function() {
|
||||
if (error.stack.indexOf(msg) === -1) {
|
||||
pending("Stack traces don't have messages in this environment");
|
||||
}
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.util.jasmineFile()
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.private.util.jasmineFile()
|
||||
});
|
||||
const result = subject.stack(error);
|
||||
const lines = result.split('\n');
|
||||
@@ -194,18 +215,31 @@ describe('ExceptionFormatter', function() {
|
||||
});
|
||||
|
||||
it('returns null if no Error provided', function() {
|
||||
expect(new jasmineUnderTest.ExceptionFormatter().stack()).toBeNull();
|
||||
expect(new privateUnderTest.ExceptionFormatter().stack()).toBeNull();
|
||||
});
|
||||
|
||||
it('includes error properties in stack', function() {
|
||||
it("includes the error's own properties in stack", function() {
|
||||
const error = new Error('an error');
|
||||
error.someProperty = 'hello there';
|
||||
|
||||
const result = new jasmineUnderTest.ExceptionFormatter().stack(error);
|
||||
const result = new privateUnderTest.ExceptionFormatter().stack(error);
|
||||
|
||||
expect(result).toMatch(/error properties:.*someProperty.*hello there/);
|
||||
});
|
||||
|
||||
it('does not include inherited error properties', function() {
|
||||
function CustomError(msg) {
|
||||
Error.call(this, msg);
|
||||
}
|
||||
|
||||
CustomError.prototype = new Error();
|
||||
CustomError.prototype.anInheritedProp = 'something';
|
||||
const error = new CustomError('nope');
|
||||
|
||||
const result = new privateUnderTest.ExceptionFormatter().stack(error);
|
||||
expect(result).not.toContain('anInheritedProp');
|
||||
});
|
||||
|
||||
describe('When omitMessage is true', function() {
|
||||
it('filters the message from V8-style stack traces', function() {
|
||||
const error = {
|
||||
@@ -217,7 +251,7 @@ describe('ExceptionFormatter', function() {
|
||||
' at fn3 (http://localhost:8888/__jasmine__/jasmine.js:4320:20)\n' +
|
||||
' at fn4 (http://localhost:8888/__spec__/core/UtilSpec.js:110:19)\n'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error, { omitMessage: true });
|
||||
@@ -236,7 +270,7 @@ describe('ExceptionFormatter', function() {
|
||||
'fn2@http://localhost:8888/__jasmine__/jasmine.js:4320:27\n' +
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28'
|
||||
};
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: 'http://localhost:8888/__jasmine__/jasmine.js'
|
||||
});
|
||||
const result = subject.stack(error, { omitMessage: true });
|
||||
@@ -249,12 +283,68 @@ describe('ExceptionFormatter', function() {
|
||||
|
||||
it('ensures that stack traces do not include the message in this environment', function() {
|
||||
const error = new Error('an error');
|
||||
const subject = new jasmineUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.util.jasmineFile()
|
||||
const subject = new privateUnderTest.ExceptionFormatter({
|
||||
jasmineFile: jasmine.private.util.jasmineFile()
|
||||
});
|
||||
const result = subject.stack(error, { omitMessage: true });
|
||||
expect(result).not.toContain('an error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the error has a cause property', function() {
|
||||
it('recursively includes the cause in the stack trace in this environment', function() {
|
||||
const subject = new privateUnderTest.ExceptionFormatter();
|
||||
const rootCause = new Error('root cause');
|
||||
const proximateCause = new Error('proximate cause', {
|
||||
cause: rootCause
|
||||
});
|
||||
const symptom = new Error('symptom', { cause: proximateCause });
|
||||
|
||||
const lines = subject.stack(symptom).split('\n');
|
||||
// Not all environments include the message in the stack trace.
|
||||
const hasRootMessage = lines[0].indexOf('symptom') !== -1;
|
||||
const firstSymptomStackIx = hasRootMessage ? 1 : 0;
|
||||
|
||||
expect(lines[firstSymptomStackIx])
|
||||
.withContext('first symptom stack frame')
|
||||
.toContain('ExceptionFormatterSpec.js');
|
||||
const proximateCauseMsgIx = lines.indexOf(
|
||||
'Caused by: Error: proximate cause'
|
||||
);
|
||||
expect(proximateCauseMsgIx)
|
||||
.withContext('index of proximate cause message')
|
||||
.toBeGreaterThan(firstSymptomStackIx);
|
||||
expect(lines[proximateCauseMsgIx + 1])
|
||||
.withContext('first proximate cause stack frame')
|
||||
.toContain('ExceptionFormatterSpec.js');
|
||||
const rootCauseMsgIx = lines.indexOf('Caused by: Error: root cause');
|
||||
expect(rootCauseMsgIx)
|
||||
.withContext('index of root cause message')
|
||||
.toBeGreaterThan(proximateCauseMsgIx + 1);
|
||||
expect(lines[rootCauseMsgIx + 1])
|
||||
.withContext('first root cause stack frame')
|
||||
.toContain('ExceptionFormatterSpec.js');
|
||||
});
|
||||
|
||||
it('does not throw if cause is a non Error', function() {
|
||||
const formatter = new privateUnderTest.ExceptionFormatter();
|
||||
|
||||
expect(function() {
|
||||
formatter.stack(
|
||||
new Error('error', {
|
||||
cause: function() {}
|
||||
})
|
||||
);
|
||||
}).not.toThrowError();
|
||||
|
||||
expect(function() {
|
||||
formatter.stack(
|
||||
new Error('error', {
|
||||
cause: 'another error'
|
||||
})
|
||||
);
|
||||
}).not.toThrowError();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,14 +2,14 @@ describe('Exceptions:', function() {
|
||||
let env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env = new privateUnderTest.Env();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
env.cleanup_();
|
||||
});
|
||||
|
||||
it('should handle exceptions thrown, but continue', function(done) {
|
||||
it('should handle exceptions thrown, but continue', async function() {
|
||||
const secondTest = jasmine.createSpy('second test');
|
||||
env.describe('Suite for handles exceptions', function() {
|
||||
env.it(
|
||||
@@ -24,15 +24,12 @@ describe('Exceptions:', function() {
|
||||
);
|
||||
});
|
||||
|
||||
const expectations = function() {
|
||||
expect(secondTest).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
await env.execute();
|
||||
|
||||
env.execute(null, expectations);
|
||||
expect(secondTest).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should handle exceptions thrown directly in top-level describe blocks and continue', function(done) {
|
||||
it('should handle exceptions thrown directly in top-level describe blocks and continue', async function() {
|
||||
const secondDescribe = jasmine
|
||||
.createSpy('second describe')
|
||||
.and.callFake(function() {
|
||||
@@ -47,11 +44,8 @@ describe('Exceptions:', function() {
|
||||
});
|
||||
env.describe("a suite that doesn't throw an exception", secondDescribe);
|
||||
|
||||
const expectations = function() {
|
||||
expect(secondDescribe).toHaveBeenCalled();
|
||||
done();
|
||||
};
|
||||
await env.execute();
|
||||
|
||||
env.execute(null, expectations);
|
||||
expect(secondDescribe).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ describe('ExpectationFilterChain', function() {
|
||||
it('returns a new filter chain with the added filter', function() {
|
||||
const first = jasmine.createSpy('first'),
|
||||
second = jasmine.createSpy('second'),
|
||||
orig = new jasmineUnderTest.ExpectationFilterChain({
|
||||
orig = new privateUnderTest.ExpectationFilterChain({
|
||||
modifyFailureMessage: first
|
||||
}),
|
||||
added = orig.addFilter({ selectComparisonFunc: second });
|
||||
@@ -15,7 +15,7 @@ describe('ExpectationFilterChain', function() {
|
||||
});
|
||||
|
||||
it('does not modify the original filter chain', function() {
|
||||
const orig = new jasmineUnderTest.ExpectationFilterChain({}),
|
||||
const orig = new privateUnderTest.ExpectationFilterChain({}),
|
||||
f = jasmine.createSpy('f');
|
||||
|
||||
orig.addFilter({ selectComparisonFunc: f });
|
||||
@@ -28,7 +28,7 @@ describe('ExpectationFilterChain', function() {
|
||||
describe('#selectComparisonFunc', function() {
|
||||
describe('When no filters have #selectComparisonFunc', function() {
|
||||
it('returns undefined', function() {
|
||||
const chain = new jasmineUnderTest.ExpectationFilterChain();
|
||||
const chain = new privateUnderTest.ExpectationFilterChain();
|
||||
chain.addFilter({});
|
||||
expect(chain.selectComparisonFunc()).toBeUndefined();
|
||||
});
|
||||
@@ -38,7 +38,7 @@ describe('ExpectationFilterChain', function() {
|
||||
it('calls the first filter that has #selectComparisonFunc', function() {
|
||||
const first = jasmine.createSpy('first').and.returnValue('first'),
|
||||
second = jasmine.createSpy('second').and.returnValue('second'),
|
||||
chain = new jasmineUnderTest.ExpectationFilterChain()
|
||||
chain = new privateUnderTest.ExpectationFilterChain()
|
||||
.addFilter({ selectComparisonFunc: first })
|
||||
.addFilter({ selectComparisonFunc: second }),
|
||||
matcher = {},
|
||||
@@ -54,7 +54,7 @@ describe('ExpectationFilterChain', function() {
|
||||
describe('#buildFailureMessage', function() {
|
||||
describe('When no filters have #buildFailureMessage', function() {
|
||||
it('returns undefined', function() {
|
||||
const chain = new jasmineUnderTest.ExpectationFilterChain();
|
||||
const chain = new privateUnderTest.ExpectationFilterChain();
|
||||
chain.addFilter({});
|
||||
expect(chain.buildFailureMessage()).toBeUndefined();
|
||||
});
|
||||
@@ -64,7 +64,7 @@ describe('ExpectationFilterChain', function() {
|
||||
it('calls the first filter that has #buildFailureMessage', function() {
|
||||
const first = jasmine.createSpy('first').and.returnValue('first'),
|
||||
second = jasmine.createSpy('second').and.returnValue('second'),
|
||||
chain = new jasmineUnderTest.ExpectationFilterChain()
|
||||
chain = new privateUnderTest.ExpectationFilterChain()
|
||||
.addFilter({ buildFailureMessage: first })
|
||||
.addFilter({ buildFailureMessage: second }),
|
||||
matcherResult = { pass: false },
|
||||
@@ -94,7 +94,7 @@ describe('ExpectationFilterChain', function() {
|
||||
describe('#modifyFailureMessage', function() {
|
||||
describe('When no filters have #modifyFailureMessage', function() {
|
||||
it('returns the original message', function() {
|
||||
const chain = new jasmineUnderTest.ExpectationFilterChain();
|
||||
const chain = new privateUnderTest.ExpectationFilterChain();
|
||||
chain.addFilter({});
|
||||
expect(chain.modifyFailureMessage('msg')).toEqual('msg');
|
||||
});
|
||||
@@ -104,7 +104,7 @@ describe('ExpectationFilterChain', function() {
|
||||
it('calls the first filter that has #modifyFailureMessage', function() {
|
||||
const first = jasmine.createSpy('first').and.returnValue('first'),
|
||||
second = jasmine.createSpy('second').and.returnValue('second'),
|
||||
chain = new jasmineUnderTest.ExpectationFilterChain()
|
||||
chain = new privateUnderTest.ExpectationFilterChain()
|
||||
.addFilter({ modifyFailureMessage: first })
|
||||
.addFilter({ modifyFailureMessage: second }),
|
||||
result = chain.modifyFailureMessage('original');
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
describe('buildExpectationResult', function() {
|
||||
it('defaults to passed', function() {
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
passed: 'some-value'
|
||||
});
|
||||
expect(result.passed).toBe('some-value');
|
||||
});
|
||||
|
||||
it('message defaults to Passed for passing specs', function() {
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
passed: true,
|
||||
message: 'some-value'
|
||||
});
|
||||
expect(result.message).toBe('Passed.');
|
||||
});
|
||||
|
||||
it('message returns the message for failing expectations', function() {
|
||||
const 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() {
|
||||
const fakeError = { message: 'foo' },
|
||||
messageFormatter = jasmine
|
||||
.createSpy('exception message formatter')
|
||||
.and.returnValue(fakeError.message);
|
||||
|
||||
const 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() {
|
||||
const fakeError = { stack: 'foo' },
|
||||
stackFormatter = jasmine
|
||||
.createSpy('stack formatter')
|
||||
.and.returnValue(fakeError.stack);
|
||||
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
passed: false,
|
||||
error: fakeError,
|
||||
stackFormatter: stackFormatter
|
||||
});
|
||||
|
||||
expect(stackFormatter).toHaveBeenCalledWith(fakeError, {
|
||||
omitMessage: true
|
||||
});
|
||||
expect(result.stack).toEqual('foo');
|
||||
});
|
||||
|
||||
it('delegates stack formatting to the provided formatter if there was a provided errorForStack', function() {
|
||||
const fakeError = { stack: 'foo' },
|
||||
stackFormatter = jasmine
|
||||
.createSpy('stack formatter')
|
||||
.and.returnValue(fakeError.stack);
|
||||
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
passed: false,
|
||||
errorForStack: fakeError,
|
||||
stackFormatter: stackFormatter
|
||||
});
|
||||
|
||||
expect(stackFormatter).toHaveBeenCalledWith(fakeError, {
|
||||
omitMessage: true
|
||||
});
|
||||
expect(result.stack).toEqual('foo');
|
||||
});
|
||||
|
||||
it('matcherName returns passed matcherName', function() {
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
matcherName: 'some-value'
|
||||
});
|
||||
expect(result.matcherName).toBe('some-value');
|
||||
});
|
||||
|
||||
it('expected returns passed expected', function() {
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
expected: 'some-value'
|
||||
});
|
||||
expect(result.expected).toBe('some-value');
|
||||
});
|
||||
|
||||
it('actual returns passed actual', function() {
|
||||
const result = jasmineUnderTest.buildExpectationResult({
|
||||
actual: 'some-value'
|
||||
});
|
||||
expect(result.actual).toBe('some-value');
|
||||
});
|
||||
|
||||
it('handles nodejs assertions', function() {
|
||||
if (typeof require === 'undefined') {
|
||||
return;
|
||||
}
|
||||
const assert = require('assert');
|
||||
const value = 8421;
|
||||
const expectedValue = 'JasmineExpectationTestValue';
|
||||
let error;
|
||||
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('==');
|
||||
|
||||
const 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 ==');
|
||||
});
|
||||
});
|
||||
@@ -4,7 +4,7 @@ describe('Expectation', function() {
|
||||
toFoo: function() {},
|
||||
toBar: function() {}
|
||||
},
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers
|
||||
});
|
||||
|
||||
@@ -17,9 +17,9 @@ describe('Expectation', function() {
|
||||
toQuux: function() {}
|
||||
};
|
||||
|
||||
jasmineUnderTest.Expectation.addCoreMatchers(coreMatchers);
|
||||
privateUnderTest.Expectation.addCoreMatchers(coreMatchers);
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({});
|
||||
const expectation = privateUnderTest.Expectation.factory({});
|
||||
|
||||
expect(expectation.toQuux).toBeDefined();
|
||||
});
|
||||
@@ -39,7 +39,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
matchersUtil: matchersUtil,
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
@@ -67,7 +67,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
matchersUtil: matchersUtil,
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
@@ -94,7 +94,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
matchersUtil: matchersUtil,
|
||||
actual: 'an actual',
|
||||
@@ -108,8 +108,6 @@ describe('Expectation', function() {
|
||||
passed: true,
|
||||
message: '',
|
||||
error: undefined,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
errorForStack: undefined
|
||||
});
|
||||
});
|
||||
@@ -131,7 +129,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
matchersUtil: matchersUtil,
|
||||
actual: 'an actual',
|
||||
@@ -143,8 +141,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: '',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -166,7 +162,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
actual: 'an actual',
|
||||
customMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -177,8 +173,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -202,7 +196,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -213,8 +207,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -231,10 +223,9 @@ describe('Expectation', function() {
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual';
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -247,8 +238,6 @@ describe('Expectation', function() {
|
||||
passed: true,
|
||||
message: '',
|
||||
error: undefined,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
errorForStack: undefined
|
||||
});
|
||||
});
|
||||
@@ -268,10 +257,9 @@ describe('Expectation', function() {
|
||||
return 'default message';
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual';
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
matchersUtil: matchersUtil,
|
||||
@@ -283,8 +271,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: 'default message',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -304,10 +290,9 @@ describe('Expectation', function() {
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual';
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -318,8 +303,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: 'I am a custom message',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -339,10 +322,9 @@ describe('Expectation', function() {
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual';
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -353,8 +335,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(true, {
|
||||
matcherName: 'toFoo',
|
||||
passed: true,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: '',
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -377,10 +357,9 @@ describe('Expectation', function() {
|
||||
};
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
actual = 'an actual';
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -391,8 +370,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: actual,
|
||||
message: "I'm a custom message",
|
||||
error: undefined,
|
||||
errorForStack: undefined
|
||||
@@ -416,7 +393,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
actual: 'an actual',
|
||||
customMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -427,8 +404,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: customError,
|
||||
errorForStack: undefined
|
||||
@@ -452,7 +427,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
actual: 'an actual',
|
||||
customMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -463,8 +438,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: customError,
|
||||
errorForStack: undefined
|
||||
@@ -490,7 +463,7 @@ describe('Expectation', function() {
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult');
|
||||
|
||||
const expectation = jasmineUnderTest.Expectation.factory({
|
||||
const expectation = privateUnderTest.Expectation.factory({
|
||||
actual: 'an actual',
|
||||
customMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -501,8 +474,6 @@ describe('Expectation', function() {
|
||||
expect(addExpectationResult).toHaveBeenCalledWith(false, {
|
||||
matcherName: 'toFoo',
|
||||
passed: false,
|
||||
expected: 'hello',
|
||||
actual: 'an actual',
|
||||
message: 'I am a custom message',
|
||||
error: customError,
|
||||
errorForStack: undefined
|
||||
@@ -526,7 +497,7 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
matchersUtil: matchersUtil,
|
||||
actual: 'an actual',
|
||||
@@ -554,7 +525,7 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -581,7 +552,7 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -611,7 +582,7 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
@@ -638,10 +609,10 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
pp = jasmineUnderTest.makePrettyPrinter(),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
pp = privateUnderTest.makePrettyPrinter(),
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
customMatchers: matchers,
|
||||
matchersUtil: new jasmineUnderTest.MatchersUtil({ pp: pp }),
|
||||
matchersUtil: new privateUnderTest.MatchersUtil({ pp: pp }),
|
||||
actual: 'an actual',
|
||||
addExpectationResult: addExpectationResult
|
||||
});
|
||||
@@ -674,7 +645,7 @@ describe('Expectation', function() {
|
||||
}
|
||||
},
|
||||
addExpectationResult = jasmine.createSpy('addExpectationResult'),
|
||||
expectation = jasmineUnderTest.Expectation.factory({
|
||||
expectation = privateUnderTest.Expectation.factory({
|
||||
actual: 'an actual',
|
||||
customMatchers: matchers,
|
||||
addExpectationResult: addExpectationResult
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
describe('JsApiReporter', function() {
|
||||
it('knows when a full environment is started', function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
expect(reporter.started).toBe(false);
|
||||
expect(reporter.finished).toBe(false);
|
||||
@@ -12,7 +12,7 @@ describe('JsApiReporter', function() {
|
||||
});
|
||||
|
||||
it('knows when a full environment is done', function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
expect(reporter.started).toBe(false);
|
||||
expect(reporter.finished).toBe(false);
|
||||
@@ -24,13 +24,13 @@ describe('JsApiReporter', function() {
|
||||
});
|
||||
|
||||
it("defaults to 'loaded' status", function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
expect(reporter.status()).toEqual('loaded');
|
||||
});
|
||||
|
||||
it("reports 'started' when Jasmine has started", function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
reporter.jasmineStarted();
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('JsApiReporter', function() {
|
||||
});
|
||||
|
||||
it("reports 'done' when Jasmine is done", function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
reporter.jasmineDone({});
|
||||
|
||||
@@ -46,7 +46,7 @@ describe('JsApiReporter', function() {
|
||||
});
|
||||
|
||||
it('tracks a suite', function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
|
||||
reporter.suiteStarted({
|
||||
id: 123,
|
||||
@@ -71,7 +71,7 @@ describe('JsApiReporter', function() {
|
||||
describe('#specResults', function() {
|
||||
let reporter, specResult1, specResult2;
|
||||
beforeEach(function() {
|
||||
reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
reporter = new privateUnderTest.JsApiReporter({});
|
||||
specResult1 = {
|
||||
id: 1,
|
||||
description: 'A spec'
|
||||
@@ -101,7 +101,7 @@ describe('JsApiReporter', function() {
|
||||
describe('#suiteResults', function() {
|
||||
let reporter, suiteStarted1, suiteResult1, suiteResult2;
|
||||
beforeEach(function() {
|
||||
reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
reporter = new privateUnderTest.JsApiReporter({});
|
||||
suiteStarted1 = {
|
||||
id: 1
|
||||
};
|
||||
@@ -138,7 +138,7 @@ describe('JsApiReporter', function() {
|
||||
describe('#executionTime', function() {
|
||||
it('should start the timer when jasmine starts', function() {
|
||||
const timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new jasmineUnderTest.JsApiReporter({
|
||||
reporter = new privateUnderTest.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ describe('JsApiReporter', function() {
|
||||
|
||||
it('should return the time it took the specs to run, in ms', function() {
|
||||
const timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new jasmineUnderTest.JsApiReporter({
|
||||
reporter = new privateUnderTest.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
@@ -160,7 +160,7 @@ describe('JsApiReporter', function() {
|
||||
describe("when the specs haven't finished being run", function() {
|
||||
it('should return undefined', function() {
|
||||
const timerSpy = jasmine.createSpyObj('timer', ['start', 'elapsed']),
|
||||
reporter = new jasmineUnderTest.JsApiReporter({
|
||||
reporter = new privateUnderTest.JsApiReporter({
|
||||
timer: timerSpy
|
||||
});
|
||||
|
||||
@@ -171,7 +171,7 @@ describe('JsApiReporter', function() {
|
||||
|
||||
describe('#runDetails', function() {
|
||||
it('should have details about the run', function() {
|
||||
const reporter = new jasmineUnderTest.JsApiReporter({});
|
||||
const reporter = new privateUnderTest.JsApiReporter({});
|
||||
reporter.jasmineDone({ some: { run: 'details' } });
|
||||
expect(reporter.runDetails).toEqual({ some: { run: 'details' } });
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
describe('FakeDate', function() {
|
||||
it('does not fail if no global date is found', function() {
|
||||
const fakeGlobal = {},
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
expect(function() {
|
||||
mockDate.install();
|
||||
@@ -19,7 +19,7 @@ describe('FakeDate', function() {
|
||||
};
|
||||
}),
|
||||
fakeGlobal = { Date: globalDate },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
expect(fakeGlobal.Date).toEqual(globalDate);
|
||||
mockDate.install();
|
||||
@@ -36,7 +36,7 @@ describe('FakeDate', function() {
|
||||
};
|
||||
}),
|
||||
fakeGlobal = { Date: globalDate },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
mockDate.uninstall();
|
||||
@@ -55,7 +55,7 @@ describe('FakeDate', function() {
|
||||
};
|
||||
}),
|
||||
fakeGlobal = { Date: globalDate },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -66,7 +66,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it('can accept a date as time base when installing', function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal),
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal),
|
||||
baseDate = new Date();
|
||||
|
||||
spyOn(baseDate, 'getTime').and.returnValue(123);
|
||||
@@ -77,7 +77,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it('makes real dates', function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
expect(new fakeGlobal.Date()).toEqual(jasmine.any(Date));
|
||||
@@ -97,7 +97,7 @@ describe('FakeDate', function() {
|
||||
fakeGlobal = { Date: globalDate };
|
||||
|
||||
globalDate.now = function() {};
|
||||
const mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
const mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -117,7 +117,7 @@ describe('FakeDate', function() {
|
||||
fakeGlobal = { Date: globalDate };
|
||||
|
||||
globalDate.now = function() {};
|
||||
const mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
const mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -143,7 +143,7 @@ describe('FakeDate', function() {
|
||||
fakeGlobal = { Date: globalDate };
|
||||
|
||||
globalDate.now = function() {};
|
||||
const mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
const mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -156,7 +156,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it('allows creation of a Date in a different time than the mocked time', function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -168,7 +168,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it("allows creation of a Date that isn't fully specified", function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
@@ -178,7 +178,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it('allows creation of a Date with millis', function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal),
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal),
|
||||
now = new Date(2014, 3, 15).getTime();
|
||||
|
||||
mockDate.install();
|
||||
@@ -189,7 +189,7 @@ describe('FakeDate', function() {
|
||||
|
||||
it('copies all Date properties to the mocked date', function() {
|
||||
const fakeGlobal = { Date: Date },
|
||||
mockDate = new jasmineUnderTest.MockDate(fakeGlobal);
|
||||
mockDate = new privateUnderTest.MockDate(fakeGlobal);
|
||||
|
||||
mockDate.install();
|
||||
|
||||
|
||||
176
spec/core/ParallelReportDispatcherSpec.js
Normal file
176
spec/core/ParallelReportDispatcherSpec.js
Normal file
@@ -0,0 +1,176 @@
|
||||
describe('ParallelReportDispatcher', function() {
|
||||
it('dispatches the standard reporter events', async function() {
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, {
|
||||
globalErrors: mockGlobalErrors()
|
||||
});
|
||||
const events = [
|
||||
'jasmineStarted',
|
||||
'jasmineDone',
|
||||
'suiteStarted',
|
||||
'suiteDone',
|
||||
'specStarted',
|
||||
'specDone'
|
||||
];
|
||||
const reporter = jasmine.createSpyObj('reporter', events);
|
||||
subject.addReporter(reporter);
|
||||
|
||||
for (const eventName of events) {
|
||||
const payload = { payloadFor: eventName };
|
||||
await subject[eventName](payload);
|
||||
expect(reporter[eventName]).toHaveBeenCalledWith(payload);
|
||||
}
|
||||
});
|
||||
|
||||
it('installs and uninstalls the global error handler', function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(() => {}, {
|
||||
globalErrors
|
||||
});
|
||||
|
||||
subject.installGlobalErrors();
|
||||
expect(globalErrors.install).toHaveBeenCalled();
|
||||
|
||||
subject.uninstallGlobalErrors();
|
||||
expect(globalErrors.uninstall).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles global errors from async reporters', async function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const onError = jasmine.createSpy('onError');
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||
globalErrors
|
||||
});
|
||||
const reporter = jasmine.createSpyObj('reporter', [
|
||||
'jasmineStarted',
|
||||
'jasmineDone'
|
||||
]);
|
||||
let resolveStarted;
|
||||
reporter.jasmineStarted.and.callFake(function() {
|
||||
return new Promise(function(res) {
|
||||
resolveStarted = res;
|
||||
});
|
||||
});
|
||||
subject.addReporter(reporter);
|
||||
|
||||
const promise = subject.jasmineStarted({});
|
||||
expect(globalErrors.pushListener).toHaveBeenCalled();
|
||||
expect(globalErrors.popListener).not.toHaveBeenCalled();
|
||||
const error = new Error('nope');
|
||||
globalErrors.pushListener.calls.argsFor(0)[0](error);
|
||||
expect(onError).toHaveBeenCalledWith(error);
|
||||
|
||||
resolveStarted();
|
||||
await promise;
|
||||
expect(globalErrors.popListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles done(error) from callback-style async reporters', function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const onError = jasmine.createSpy('onError');
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||
globalErrors
|
||||
});
|
||||
const reporter = jasmine.createSpyObj('reporter', [
|
||||
'jasmineStarted',
|
||||
'jasmineDone'
|
||||
]);
|
||||
let callback;
|
||||
reporter.jasmineStarted = function(event, cb) {
|
||||
callback = cb;
|
||||
};
|
||||
subject.addReporter(reporter);
|
||||
|
||||
subject.jasmineStarted({});
|
||||
|
||||
expect(callback).toBeInstanceOf(Function);
|
||||
const error = new Error('nope');
|
||||
callback(error);
|
||||
|
||||
expect(onError).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('handles done.fail() from callback-style async reporters', function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const onError = jasmine.createSpy('onError');
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||
globalErrors
|
||||
});
|
||||
const reporter = jasmine.createSpyObj('reporter', [
|
||||
'jasmineStarted',
|
||||
'jasmineDone'
|
||||
]);
|
||||
let callback;
|
||||
reporter.jasmineStarted = function(event, cb) {
|
||||
callback = cb;
|
||||
};
|
||||
subject.addReporter(reporter);
|
||||
|
||||
subject.jasmineStarted({});
|
||||
|
||||
expect(callback).toBeInstanceOf(Function);
|
||||
const error = new Error('nope');
|
||||
callback.fail(error);
|
||||
expect(onError).toHaveBeenCalledWith(error);
|
||||
onError.calls.reset();
|
||||
|
||||
callback.fail();
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
new Error('A reporter called done.fail()')
|
||||
);
|
||||
});
|
||||
|
||||
it('handles errors due to mixed async style in reporters', async function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const onError = jasmine.createSpy('onError');
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||
globalErrors
|
||||
});
|
||||
subject.addReporter({
|
||||
async jasmineStarted(event, done) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
await subject.jasmineStarted({});
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
new Error(
|
||||
'An asynchronous before/it/after function took a done callback but also returned a promise. Either remove the done callback (recommended) or change the function to not return a promise.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('handles errors due to multiple done calls in reporters', async function() {
|
||||
const globalErrors = mockGlobalErrors();
|
||||
const onError = jasmine.createSpy('onError');
|
||||
const subject = new jasmineUnderTest.ParallelReportDispatcher(onError, {
|
||||
globalErrors
|
||||
});
|
||||
subject.addReporter({
|
||||
jasmineStarted(event, done) {
|
||||
done();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
await subject.jasmineStarted({});
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
new Error(
|
||||
"An asynchronous reporter callback called its 'done' callback more than once."
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
function mockGlobalErrors() {
|
||||
const globalErrors = jasmine.createSpyObj('globalErrors', [
|
||||
'install',
|
||||
'pushListener',
|
||||
'popListener'
|
||||
]);
|
||||
|
||||
globalErrors.install.and.callFake(function() {
|
||||
globalErrors.uninstall = jasmine.createSpy('globalErrors.uninstall');
|
||||
});
|
||||
|
||||
return globalErrors;
|
||||
}
|
||||
});
|
||||
@@ -1,12 +1,12 @@
|
||||
describe('PrettyPrinter', function() {
|
||||
it('should wrap strings in single quotes', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp('some string')).toEqual("'some string'");
|
||||
expect(pp("som' string")).toEqual("'som' string'");
|
||||
});
|
||||
|
||||
it('stringifies empty string primitives and objects recognizably', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(new String(''))).toEqual(pp(''));
|
||||
expect(pp(new String(''))).toEqual("''");
|
||||
expect(pp([new String('')])).toEqual(pp(['']));
|
||||
@@ -14,7 +14,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify primitives properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(true)).toEqual('true');
|
||||
expect(pp(false)).toEqual('false');
|
||||
expect(pp(null)).toEqual('null');
|
||||
@@ -29,7 +29,7 @@ describe('PrettyPrinter', function() {
|
||||
const set = new Set();
|
||||
set.add(1);
|
||||
set.add(2);
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(set)).toEqual('Set( 1, 2 )');
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('PrettyPrinter', function() {
|
||||
set.add('a');
|
||||
set.add('b');
|
||||
set.add('c');
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(set)).toEqual("Set( 'a', 'b', ... )");
|
||||
} finally {
|
||||
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
|
||||
@@ -54,7 +54,7 @@ describe('PrettyPrinter', function() {
|
||||
it('should stringify maps properly', function() {
|
||||
const map = new Map();
|
||||
map.set(1, 2);
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(map)).toEqual('Map( [ 1, 2 ] )');
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ describe('PrettyPrinter', function() {
|
||||
map.set('a', 1);
|
||||
map.set('b', 2);
|
||||
map.set('c', 3);
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(map)).toEqual("Map( [ 'a', 1 ], [ 'b', 2 ], ... )");
|
||||
} finally {
|
||||
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = originalMaxSize;
|
||||
@@ -77,7 +77,7 @@ describe('PrettyPrinter', function() {
|
||||
|
||||
describe('stringify arrays', function() {
|
||||
it('should stringify arrays properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp([1, 2])).toEqual('[ 1, 2 ]');
|
||||
expect(pp([1, 'foo', {}, jasmine.undefined, null])).toEqual(
|
||||
"[ 1, 'foo', Object({ }), undefined, null ]"
|
||||
@@ -85,14 +85,14 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('includes symbols', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp([1, Symbol('foo'), 2])).toEqual('[ 1, Symbol(foo), 2 ]');
|
||||
});
|
||||
|
||||
it('should truncate arrays that are longer than jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH', function() {
|
||||
const originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
||||
const array = [1, 2, 3];
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
|
||||
try {
|
||||
jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH = 2;
|
||||
@@ -103,7 +103,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify arrays with properties properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const arr = [1, 2];
|
||||
arr.foo = 'bar';
|
||||
arr.baz = {};
|
||||
@@ -111,7 +111,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify empty arrays with properties properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const empty = [];
|
||||
empty.foo = 'bar';
|
||||
empty.baz = {};
|
||||
@@ -119,7 +119,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify long arrays with properties properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
||||
const long = [1, 2, 3];
|
||||
long.foo = 'bar';
|
||||
@@ -136,7 +136,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should indicate circular array references', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const array1 = [1, 2];
|
||||
const array2 = [array1];
|
||||
array1.push(array2);
|
||||
@@ -144,14 +144,14 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should not indicate circular references incorrectly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const array = [[1]];
|
||||
expect(pp(array)).toEqual('[ [ 1 ] ]');
|
||||
});
|
||||
});
|
||||
|
||||
it('should stringify objects properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp({ foo: 'bar' })).toEqual("Object({ foo: 'bar' })");
|
||||
expect(
|
||||
pp({
|
||||
@@ -164,19 +164,19 @@ describe('PrettyPrinter', function() {
|
||||
"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 ] })'
|
||||
"Object({ foo: Function 'foo', bar: [ 1, 2, 3 ] })"
|
||||
);
|
||||
});
|
||||
|
||||
it('includes symbol keys in objects', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = {};
|
||||
obj[Symbol('foo')] = 'bar';
|
||||
expect(pp(obj)).toEqual("Object({ Symbol(foo): 'bar' })");
|
||||
});
|
||||
|
||||
it('stringifies string and symbol keys differently', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const symObj = {};
|
||||
const strObj = {};
|
||||
const k = 'foo';
|
||||
@@ -188,12 +188,12 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify objects that almost look like DOM nodes', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp({ nodeType: 1 })).toEqual('Object({ nodeType: 1 })');
|
||||
});
|
||||
|
||||
it('should truncate objects with too many keys', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const originalMaxLength = jasmineUnderTest.MAX_PRETTY_PRINT_ARRAY_LENGTH;
|
||||
const long = { a: 1, b: 2, c: 3 };
|
||||
|
||||
@@ -217,7 +217,7 @@ describe('PrettyPrinter', function() {
|
||||
}
|
||||
|
||||
it('should truncate outputs that are too long', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const big = [{ a: 1, b: 'a long string' }, {}];
|
||||
|
||||
withMaxChars(34, function() {
|
||||
@@ -246,7 +246,7 @@ describe('PrettyPrinter', function() {
|
||||
.createSpy('d jasmineToString')
|
||||
.and.returnValue('')
|
||||
},
|
||||
pp = jasmineUnderTest.makePrettyPrinter();
|
||||
pp = privateUnderTest.makePrettyPrinter();
|
||||
|
||||
withMaxChars(30, function() {
|
||||
pp([{ a: a, b: b, c: c }, d]);
|
||||
@@ -256,13 +256,13 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it("should print 'null' as the constructor of an object with its own constructor property", function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp({ constructor: function() {} })).toContain('null({');
|
||||
expect(pp({ constructor: 'foo' })).toContain('null({');
|
||||
});
|
||||
|
||||
it('should not include inherited properties when stringifying an object', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const SomeClass = function SomeClass() {};
|
||||
SomeClass.prototype.foo = 'inherited foo';
|
||||
const instance = new SomeClass();
|
||||
@@ -271,7 +271,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should not recurse objects and arrays more deeply than jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const originalMaxDepth = jasmineUnderTest.MAX_PRETTY_PRINT_DEPTH;
|
||||
const nestedObject = { level1: { level2: { level3: { level4: 'leaf' } } } };
|
||||
const nestedArray = [1, [2, [3, [4, 'leaf']]]];
|
||||
@@ -300,7 +300,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify immutable circular objects', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
let frozenObject = { foo: { bar: 'baz' } };
|
||||
frozenObject.circular = frozenObject;
|
||||
frozenObject = Object.freeze(frozenObject);
|
||||
@@ -310,12 +310,12 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify RegExp objects properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(/x|y|z/)).toEqual('/x|y|z/');
|
||||
});
|
||||
|
||||
it('should indicate circular object references', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const sampleValue = { foo: 'hello' };
|
||||
sampleValue.nested = sampleValue;
|
||||
expect(pp(sampleValue)).toEqual(
|
||||
@@ -323,33 +323,33 @@ describe('PrettyPrinter', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('should indicate getters on objects as such', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
it('should use the return value of getters', function() {
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const sampleValue = {
|
||||
id: 1,
|
||||
get calculatedValue() {
|
||||
throw new Error("don't call me!");
|
||||
return 'the getter return value';
|
||||
}
|
||||
};
|
||||
expect(pp(sampleValue)).toEqual(
|
||||
'Object({ id: 1, calculatedValue: <getter> })'
|
||||
"Object({ id: 1, calculatedValue: 'the getter return value' })"
|
||||
);
|
||||
});
|
||||
|
||||
it('should not do HTML escaping of strings', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp('some <b>html string</b> &', false)).toEqual(
|
||||
"'some <b>html string</b> &'"
|
||||
);
|
||||
});
|
||||
|
||||
it('should abbreviate the global (usually window) object', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(jasmine.getGlobal())).toEqual('<global>');
|
||||
});
|
||||
|
||||
it('should stringify Date objects properly', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const now = new Date();
|
||||
expect(pp(now)).toEqual('Date(' + now.toString() + ')');
|
||||
});
|
||||
@@ -358,8 +358,8 @@ describe('PrettyPrinter', function() {
|
||||
let env, pp;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
pp = jasmineUnderTest.makePrettyPrinter();
|
||||
env = new privateUnderTest.Env();
|
||||
pp = privateUnderTest.makePrettyPrinter();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -371,12 +371,12 @@ describe('PrettyPrinter', function() {
|
||||
someFunction: function() {}
|
||||
};
|
||||
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return [];
|
||||
},
|
||||
createSpy: function(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
return privateUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -390,15 +390,15 @@ describe('PrettyPrinter', function() {
|
||||
const TestObject = {
|
||||
someFunction: function() {}
|
||||
},
|
||||
env = new jasmineUnderTest.Env(),
|
||||
pp = jasmineUnderTest.makePrettyPrinter();
|
||||
env = new privateUnderTest.Env(),
|
||||
pp = privateUnderTest.makePrettyPrinter();
|
||||
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return [];
|
||||
},
|
||||
createSpy: function(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
return privateUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -410,7 +410,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify objects that implement jasmineToString', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = {
|
||||
jasmineToString: function() {
|
||||
return 'strung';
|
||||
@@ -421,7 +421,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should pass itself to jasmineToString', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter([]);
|
||||
const pp = privateUnderTest.makePrettyPrinter([]);
|
||||
const obj = {
|
||||
jasmineToString: jasmine.createSpy('jasmineToString').and.returnValue('')
|
||||
};
|
||||
@@ -431,7 +431,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify objects that implement custom toString', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = {
|
||||
toString: function() {
|
||||
return 'my toString';
|
||||
@@ -450,12 +450,12 @@ describe('PrettyPrinter', function() {
|
||||
};
|
||||
|
||||
expect(pp(objFromOtherContext)).toEqual(
|
||||
"Object({ foo: 'bar', toString: Function })"
|
||||
"Object({ foo: 'bar', toString: Function 'toString' })"
|
||||
);
|
||||
});
|
||||
|
||||
it("should stringify objects have have a toString that isn't a function", function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = {
|
||||
toString: 'foo'
|
||||
};
|
||||
@@ -464,7 +464,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should stringify objects from anonymous constructors with custom toString', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const MyAnonymousConstructor = (function() {
|
||||
return function() {};
|
||||
})();
|
||||
@@ -477,8 +477,19 @@ describe('PrettyPrinter', function() {
|
||||
expect(pp(a)).toEqual('<anonymous>({ })');
|
||||
});
|
||||
|
||||
it('stringifies functions with names', function() {
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(foo)).toEqual("Function 'foo'");
|
||||
function foo() {}
|
||||
});
|
||||
|
||||
it('stringifies functions without names', function() {
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
expect(pp(function() {})).toEqual('Function');
|
||||
});
|
||||
|
||||
it('should handle objects with null prototype', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = Object.create(null);
|
||||
obj.foo = 'bar';
|
||||
|
||||
@@ -486,7 +497,7 @@ describe('PrettyPrinter', function() {
|
||||
});
|
||||
|
||||
it('should gracefully handle objects with invalid toString implementations', function() {
|
||||
const pp = jasmineUnderTest.makePrettyPrinter();
|
||||
const pp = privateUnderTest.makePrettyPrinter();
|
||||
const obj = {
|
||||
foo: {
|
||||
toString: function() {
|
||||
@@ -534,7 +545,7 @@ describe('PrettyPrinter', function() {
|
||||
return '3rd: ' + obj.foo;
|
||||
}
|
||||
],
|
||||
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
pp = privateUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
obj = { foo: 'bar' };
|
||||
|
||||
expect(pp(obj)).toEqual('2nd: bar');
|
||||
@@ -546,7 +557,7 @@ describe('PrettyPrinter', function() {
|
||||
return undefined;
|
||||
}
|
||||
],
|
||||
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
pp = privateUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
obj = { foo: 'bar' };
|
||||
|
||||
expect(pp(obj)).toEqual("Object({ foo: 'bar' })");
|
||||
@@ -566,7 +577,7 @@ describe('PrettyPrinter', function() {
|
||||
return '3rd: ' + obj.foo;
|
||||
}
|
||||
],
|
||||
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
pp = privateUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
obj = { foo: 'bar' };
|
||||
|
||||
expect(pp.customFormat_(obj)).toEqual('2nd: bar');
|
||||
@@ -578,7 +589,7 @@ describe('PrettyPrinter', function() {
|
||||
return undefined;
|
||||
}
|
||||
],
|
||||
pp = jasmineUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
pp = privateUnderTest.makePrettyPrinter(customObjectFormatters),
|
||||
obj = { foo: 'bar' };
|
||||
|
||||
expect(pp.customFormat_(obj)).toBeUndefined();
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
describe('QueueRunner', function() {
|
||||
it('validates that queueableFns are truthy', function() {
|
||||
expect(function() {
|
||||
new privateUnderTest.QueueRunner({
|
||||
queueableFns: [undefined]
|
||||
});
|
||||
}).toThrowError('Received a falsy queueableFn');
|
||||
});
|
||||
|
||||
it('validates that queueableFns have fn properties', function() {
|
||||
expect(function() {
|
||||
new privateUnderTest.QueueRunner({
|
||||
queueableFns: [{ fn: undefined }]
|
||||
});
|
||||
}).toThrowError('Received a queueableFn with no fn');
|
||||
});
|
||||
|
||||
it("runs all the functions it's passed", function() {
|
||||
const calls = [],
|
||||
queueableFn1 = { fn: jasmine.createSpy('fn1') },
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2]
|
||||
});
|
||||
queueableFn1.fn.and.callFake(function() {
|
||||
@@ -28,14 +44,14 @@ describe('QueueRunner', function() {
|
||||
done();
|
||||
}
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2, queueableFn3]
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
const context = queueableFn1.fn.calls.first().object;
|
||||
expect(context).toEqual(new jasmineUnderTest.UserContext());
|
||||
expect(context).toEqual(new privateUnderTest.UserContext());
|
||||
expect(queueableFn2.fn.calls.first().object).toBe(context);
|
||||
expect(asyncContext).toBe(context);
|
||||
});
|
||||
@@ -75,7 +91,7 @@ describe('QueueRunner', function() {
|
||||
setTimeout(done, 100);
|
||||
}
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2, queueableFn3],
|
||||
onComplete: onComplete
|
||||
});
|
||||
@@ -113,7 +129,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
@@ -141,7 +157,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
@@ -173,7 +189,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn,
|
||||
onComplete: function() {
|
||||
@@ -185,43 +201,20 @@ describe('QueueRunner', function() {
|
||||
|
||||
queueRunner.execute();
|
||||
});
|
||||
|
||||
it('does not log a deprecation', function(done) {
|
||||
const err = new Error('foo'),
|
||||
queueableFn1 = {
|
||||
fn: function() {
|
||||
return Promise.resolve(err);
|
||||
}
|
||||
},
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1],
|
||||
deprecated: deprecated,
|
||||
onComplete: function() {
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
});
|
||||
});
|
||||
|
||||
describe('and the argument is not an Error', function() {
|
||||
it('does not log a deprecation or report a failure', function(done) {
|
||||
it('does not report a failure', function(done) {
|
||||
const queueableFn1 = {
|
||||
fn: function() {
|
||||
return Promise.resolve('not an error');
|
||||
}
|
||||
},
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1],
|
||||
deprecated: deprecated,
|
||||
fail: failFn,
|
||||
onComplete: function() {
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
expect(failFn).not.toHaveBeenCalled();
|
||||
done();
|
||||
}
|
||||
@@ -234,7 +227,7 @@ describe('QueueRunner', function() {
|
||||
});
|
||||
|
||||
it('does not cause an explicit fail if execution is being stopped', function() {
|
||||
const err = new jasmineUnderTest.StopExecutionError('foo'),
|
||||
const err = new privateUnderTest.StopExecutionError('foo'),
|
||||
queueableFn1 = {
|
||||
fn: function(done) {
|
||||
setTimeout(function() {
|
||||
@@ -244,7 +237,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
failFn = jasmine.createSpy('fail'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
fail: failFn
|
||||
});
|
||||
@@ -262,12 +255,11 @@ describe('QueueRunner', function() {
|
||||
|
||||
it("sets a timeout if requested for asynchronous functions so they don't go on forever", function() {
|
||||
const timeout = 3,
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
beforeFn = { fn: function(done) {}, type: 'before', timeout: timeout },
|
||||
queueableFn = { fn: jasmine.createSpy('fn'), type: 'queueable' },
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [beforeFn, queueableFn],
|
||||
onComplete: onComplete,
|
||||
onException: onException
|
||||
@@ -295,7 +287,7 @@ describe('QueueRunner', function() {
|
||||
};
|
||||
const onComplete = jasmine.createSpy('onComplete');
|
||||
const onMultipleDone = jasmine.createSpy('onMultipleDone');
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onComplete: onComplete,
|
||||
onMultipleDone: onMultipleDone
|
||||
@@ -310,12 +302,11 @@ describe('QueueRunner', function() {
|
||||
});
|
||||
|
||||
it('by default does not set a timeout for asynchronous functions', function() {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const beforeFn = { fn: function(done) {} },
|
||||
queueableFn = { fn: jasmine.createSpy('fn') },
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [beforeFn, queueableFn],
|
||||
onComplete: onComplete,
|
||||
onException: onException
|
||||
@@ -333,14 +324,13 @@ describe('QueueRunner', function() {
|
||||
|
||||
it('clears the timeout when an async function throws an exception, to prevent additional exception reporting', function() {
|
||||
const queueableFn = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fn: function(done) {
|
||||
throw new Error('error!');
|
||||
}
|
||||
},
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onComplete: onComplete,
|
||||
onException: onException
|
||||
@@ -363,7 +353,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onComplete: onComplete,
|
||||
onException: onException
|
||||
@@ -387,7 +377,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
||||
onMultipleDone = jasmine.createSpy('onMultipleDone'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn],
|
||||
onMultipleDone: onMultipleDone
|
||||
});
|
||||
@@ -406,17 +396,12 @@ describe('QueueRunner', function() {
|
||||
}
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFn') },
|
||||
deprecated = jasmine.createSpy('deprecated'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
deprecated: deprecated,
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn]
|
||||
});
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick(1);
|
||||
expect(nextQueueableFn.fn.calls.count()).toEqual(1);
|
||||
// Don't issue a deprecation. The error already tells the user that
|
||||
// something went wrong.
|
||||
expect(deprecated).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return a null when you call done', function() {
|
||||
@@ -427,7 +412,7 @@ describe('QueueRunner', function() {
|
||||
doneReturn = done();
|
||||
}
|
||||
};
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn]
|
||||
});
|
||||
|
||||
@@ -437,7 +422,6 @@ describe('QueueRunner', function() {
|
||||
|
||||
it('continues running functions when an exception is thrown in async code without timing out', function() {
|
||||
const queueableFn = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fn: function(done) {
|
||||
throwAsync();
|
||||
},
|
||||
@@ -449,7 +433,7 @@ describe('QueueRunner', function() {
|
||||
pushListener: jasmine.createSpy('pushListener'),
|
||||
popListener: jasmine.createSpy('popListener')
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn],
|
||||
onException: onException,
|
||||
globalErrors: globalErrors
|
||||
@@ -487,6 +471,31 @@ describe('QueueRunner', function() {
|
||||
expect(nextQueueableFn.fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles a global error event with a message but no error', function() {
|
||||
const queueableFn = {
|
||||
fn: function(done) {
|
||||
const currentHandler = globalErrors.pushListener.calls.mostRecent()
|
||||
.args[0];
|
||||
currentHandler(undefined, { message: 'nope' });
|
||||
},
|
||||
timeout: 1
|
||||
};
|
||||
const onException = jasmine.createSpy('onException');
|
||||
const globalErrors = {
|
||||
pushListener: jasmine.createSpy('pushListener'),
|
||||
popListener: jasmine.createSpy('popListener')
|
||||
};
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onException: onException,
|
||||
globalErrors: globalErrors
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
|
||||
expect(onException).toHaveBeenCalledWith('nope');
|
||||
});
|
||||
|
||||
it('handles exceptions thrown while waiting for the stack to clear', function() {
|
||||
const queueableFn = {
|
||||
fn: function(done) {
|
||||
@@ -504,7 +513,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
clearStack = jasmine.createSpy('clearStack'),
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
globalErrors: globalErrors,
|
||||
clearStack: clearStack,
|
||||
@@ -520,6 +529,40 @@ describe('QueueRunner', function() {
|
||||
clearStack.calls.argsFor(0)[0]();
|
||||
expect(onException).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('handles a global error event with no error while waiting for the stack to clear', function() {
|
||||
const queueableFn = {
|
||||
fn: function(done) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
const errorListeners = [];
|
||||
const globalErrors = {
|
||||
pushListener: function(f) {
|
||||
errorListeners.push(f);
|
||||
},
|
||||
popListener: function() {
|
||||
errorListeners.pop();
|
||||
}
|
||||
};
|
||||
const clearStack = jasmine.createSpy('clearStack');
|
||||
const onException = jasmine.createSpy('onException');
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
globalErrors: globalErrors,
|
||||
clearStack: clearStack,
|
||||
onException: onException
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
jasmine.clock().tick();
|
||||
expect(clearStack).toHaveBeenCalled();
|
||||
expect(errorListeners.length).toEqual(1);
|
||||
errorListeners[0](undefined, { message: 'nope' });
|
||||
|
||||
clearStack.calls.argsFor(0)[0]();
|
||||
expect(onException).toHaveBeenCalledWith('nope');
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a function that returns a promise', function() {
|
||||
@@ -560,7 +603,7 @@ describe('QueueRunner', function() {
|
||||
return p2;
|
||||
}
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
onComplete: onComplete
|
||||
});
|
||||
@@ -591,7 +634,7 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
queueableFn2 = { fn: jasmine.createSpy('fn2') },
|
||||
onExceptionCallback = jasmine.createSpy('on exception callback'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn1, queueableFn2],
|
||||
onException: onExceptionCallback
|
||||
});
|
||||
@@ -609,13 +652,12 @@ describe('QueueRunner', function() {
|
||||
|
||||
it('issues an error if the function also takes a parameter', function() {
|
||||
const queueableFn = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fn: function(done) {
|
||||
return new StubPromise();
|
||||
}
|
||||
},
|
||||
onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onException: onException
|
||||
});
|
||||
@@ -623,18 +665,20 @@ describe('QueueRunner', function() {
|
||||
queueRunner.execute();
|
||||
|
||||
expect(onException).toHaveBeenCalledWith(
|
||||
'An asynchronous ' +
|
||||
'before/it/after function took a done callback but also returned a ' +
|
||||
'promise. ' +
|
||||
'Either remove the done callback (recommended) or change the function ' +
|
||||
'to not return a promise.'
|
||||
new Error(
|
||||
'An asynchronous ' +
|
||||
'before/it/after function took a done callback but also returned a ' +
|
||||
'promise. ' +
|
||||
'Either remove the done callback (recommended) or change the function ' +
|
||||
'to not return a promise.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('issues a more specific error if the function is `async`', function() {
|
||||
eval('var fn = async function(done){};');
|
||||
async function fn(done) {}
|
||||
const onException = jasmine.createSpy('onException'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [{ fn: fn }],
|
||||
onException: onException
|
||||
});
|
||||
@@ -642,40 +686,29 @@ describe('QueueRunner', function() {
|
||||
queueRunner.execute();
|
||||
|
||||
expect(onException).toHaveBeenCalledWith(
|
||||
'An asynchronous ' +
|
||||
'before/it/after function was defined with the async keyword but ' +
|
||||
'also took a done callback. Either remove the done callback ' +
|
||||
'(recommended) or remove the async keyword.'
|
||||
new Error(
|
||||
'An asynchronous ' +
|
||||
'before/it/after function was defined with the async keyword but ' +
|
||||
'also took a done callback. Either remove the done callback ' +
|
||||
'(recommended) or remove the async keyword.'
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('passes the error instance to exception handlers in HTML browsers', function() {
|
||||
it('passes final errors to exception handlers', function() {
|
||||
const error = new Error('fake error'),
|
||||
onExceptionCallback = jasmine.createSpy('on exception callback'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
onException: onExceptionCallback
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
queueRunner.handleFinalError(error.message, 'fake.js', 1, 1, error);
|
||||
queueRunner.handleFinalError(error);
|
||||
|
||||
expect(onExceptionCallback).toHaveBeenCalledWith(error);
|
||||
});
|
||||
|
||||
it('passes the first argument to exception handlers for compatibility', function() {
|
||||
const 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() {
|
||||
const queueableFn = {
|
||||
type: 'queueable',
|
||||
@@ -684,7 +717,7 @@ describe('QueueRunner', function() {
|
||||
}
|
||||
},
|
||||
onExceptionCallback = jasmine.createSpy('on exception callback'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onException: onExceptionCallback
|
||||
});
|
||||
@@ -696,13 +729,12 @@ describe('QueueRunner', function() {
|
||||
|
||||
it('continues running the functions even after an exception is thrown in an async spec', function() {
|
||||
const queueableFn = {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
fn: function(done) {
|
||||
throw new Error('error');
|
||||
}
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn]
|
||||
});
|
||||
|
||||
@@ -715,7 +747,7 @@ describe('QueueRunner', function() {
|
||||
const SkipPolicy = jasmine.createSpy('SkipPolicy ctor');
|
||||
const queueableFns = [{ fn: () => {} }, { fn: () => {} }];
|
||||
|
||||
new jasmineUnderTest.QueueRunner({
|
||||
new privateUnderTest.QueueRunner({
|
||||
queueableFns,
|
||||
SkipPolicy
|
||||
});
|
||||
@@ -737,7 +769,7 @@ describe('QueueRunner', function() {
|
||||
skipPolicy.skipTo.and.callFake(function(lastRanIx) {
|
||||
return lastRanIx === 0 ? 2 : lastRanIx + 1;
|
||||
});
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns,
|
||||
SkipPolicy: function() {
|
||||
return skipPolicy;
|
||||
@@ -758,7 +790,7 @@ describe('QueueRunner', function() {
|
||||
it('throws if the skip policy returns the current fn', function() {
|
||||
const skipPolicy = { skipTo: i => i };
|
||||
const queueableFns = [{ fn: () => {} }];
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns,
|
||||
SkipPolicy: function() {
|
||||
return skipPolicy;
|
||||
@@ -784,17 +816,17 @@ describe('QueueRunner', function() {
|
||||
type: 'specCleanup'
|
||||
},
|
||||
onComplete = jasmine.createSpy('onComplete'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn, cleanupFn],
|
||||
onComplete: onComplete,
|
||||
SkipPolicy: jasmineUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
expect(nextQueueableFn.fn).not.toHaveBeenCalled();
|
||||
expect(cleanupFn.fn).toHaveBeenCalled();
|
||||
expect(onComplete).toHaveBeenCalledWith(
|
||||
jasmine.any(jasmineUnderTest.StopExecutionError)
|
||||
jasmine.any(privateUnderTest.StopExecutionError)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -810,9 +842,9 @@ describe('QueueRunner', function() {
|
||||
fn: jasmine.createSpy('cleanupFn2'),
|
||||
type: 'afterEach'
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, cleanupFn1, cleanupFn2],
|
||||
SkipPolicy: jasmineUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
@@ -841,7 +873,7 @@ describe('QueueRunner', function() {
|
||||
fn: jasmine.createSpy('cleanup'),
|
||||
type: 'specCleanup'
|
||||
};
|
||||
const queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
const queueRunner = new privateUnderTest.QueueRunner({
|
||||
globalErrors: {
|
||||
pushListener: function(f) {
|
||||
errorListeners.push(f);
|
||||
@@ -851,7 +883,7 @@ describe('QueueRunner', function() {
|
||||
}
|
||||
},
|
||||
queueableFns: [queueableFn, nextQueueableFn, cleanupFn],
|
||||
SkipPolicy: jasmineUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
@@ -870,9 +902,9 @@ describe('QueueRunner', function() {
|
||||
},
|
||||
nextQueueableFn = { fn: jasmine.createSpy('nextFunction') },
|
||||
cleanupFn = { fn: jasmine.createSpy('cleanup'), type: 'specCleanup' },
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn, cleanupFn],
|
||||
SkipPolicy: jasmineUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
@@ -892,9 +924,9 @@ describe('QueueRunner', function() {
|
||||
fn: jasmine.createSpy('cleanup'),
|
||||
type: 'specCleanup'
|
||||
},
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn, nextQueueableFn, cleanupFn],
|
||||
SkipPolicy: jasmineUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy
|
||||
});
|
||||
|
||||
queueRunner.execute();
|
||||
@@ -908,7 +940,7 @@ describe('QueueRunner', function() {
|
||||
it('calls a provided complete callback when done', function() {
|
||||
const queueableFn = { fn: jasmine.createSpy('fn') },
|
||||
completeCallback = jasmine.createSpy('completeCallback'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [queueableFn],
|
||||
onComplete: completeCallback
|
||||
});
|
||||
@@ -936,7 +968,7 @@ describe('QueueRunner', function() {
|
||||
afterFn = { fn: jasmine.createSpy('afterFn') },
|
||||
completeCallback = jasmine.createSpy('completeCallback'),
|
||||
clearStack = jasmine.createSpy('clearStack'),
|
||||
queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [asyncFn, afterFn],
|
||||
clearStack: clearStack,
|
||||
onComplete: completeCallback
|
||||
@@ -960,7 +992,7 @@ describe('QueueRunner', function() {
|
||||
const fn = jasmine.createSpy('fn1');
|
||||
|
||||
this.fn = fn;
|
||||
this.queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
this.queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [{ fn: fn }]
|
||||
});
|
||||
});
|
||||
@@ -973,7 +1005,7 @@ describe('QueueRunner', function() {
|
||||
|
||||
this.queueRunner.execute();
|
||||
|
||||
expect(context.constructor).toBe(jasmineUnderTest.UserContext);
|
||||
expect(context.constructor).toBe(privateUnderTest.UserContext);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -983,8 +1015,8 @@ describe('QueueRunner', function() {
|
||||
let context;
|
||||
|
||||
this.fn = fn;
|
||||
this.context = context = new jasmineUnderTest.UserContext();
|
||||
this.queueRunner = new jasmineUnderTest.QueueRunner({
|
||||
this.context = context = new privateUnderTest.UserContext();
|
||||
this.queueRunner = new privateUnderTest.QueueRunner({
|
||||
queueableFns: [{ fn: fn }],
|
||||
userContext: context
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
describe('ReportDispatcher', function() {
|
||||
it('builds an interface of requested methods', function() {
|
||||
const dispatcher = new jasmineUnderTest.ReportDispatcher([
|
||||
const dispatcher = new privateUnderTest.ReportDispatcher([
|
||||
'foo',
|
||||
'bar',
|
||||
'baz'
|
||||
@@ -12,21 +12,20 @@ describe('ReportDispatcher', function() {
|
||||
});
|
||||
|
||||
it('dispatches requested methods to added reporters', function() {
|
||||
const queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(
|
||||
const runQueue = jasmine.createSpy('runQueue'),
|
||||
dispatcher = new privateUnderTest.ReportDispatcher(
|
||||
['foo', 'bar'],
|
||||
queueRunnerFactory
|
||||
runQueue
|
||||
),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
anotherReporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.addReporter(anotherReporter);
|
||||
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
dispatcher.foo({ an: 'event' });
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [
|
||||
{ fn: jasmine.any(Function) },
|
||||
@@ -36,20 +35,20 @@ describe('ReportDispatcher', function() {
|
||||
})
|
||||
);
|
||||
|
||||
let fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
let fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(reporter.foo).toHaveBeenCalledWith({ an: 'event' });
|
||||
expect(reporter.foo.calls.mostRecent().object).toBe(reporter);
|
||||
|
||||
fns[1].fn();
|
||||
expect(anotherReporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(anotherReporter.foo).toHaveBeenCalledWith({ an: 'event' });
|
||||
expect(anotherReporter.foo.calls.mostRecent().object).toBe(anotherReporter);
|
||||
|
||||
queueRunnerFactory.calls.reset();
|
||||
runQueue.calls.reset();
|
||||
|
||||
dispatcher.bar('a', 'b', completeCallback);
|
||||
dispatcher.bar({ another: 'event' });
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [
|
||||
{ fn: jasmine.any(Function) },
|
||||
@@ -59,26 +58,56 @@ describe('ReportDispatcher', function() {
|
||||
})
|
||||
);
|
||||
|
||||
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
expect(reporter.bar).toHaveBeenCalledWith({ another: 'event' });
|
||||
|
||||
fns[1].fn();
|
||||
expect(anotherReporter.bar).toHaveBeenCalledWith('a', 'b');
|
||||
expect(anotherReporter.bar).toHaveBeenCalledWith({ another: 'event' });
|
||||
});
|
||||
|
||||
it('passes each reporter a separate deep copy of the event', function() {
|
||||
const runQueue = jasmine.createSpy('runQueue');
|
||||
const dispatcher = new privateUnderTest.ReportDispatcher(
|
||||
['foo', 'bar'],
|
||||
runQueue
|
||||
);
|
||||
const reporter = jasmine.createSpyObj('reporter', ['foo']);
|
||||
const anotherReporter = jasmine.createSpyObj('anotherReporter', ['foo']);
|
||||
const event = {
|
||||
child: {
|
||||
grandchild: 'something'
|
||||
}
|
||||
};
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.addReporter(anotherReporter);
|
||||
|
||||
dispatcher.foo(event);
|
||||
|
||||
for (const fn of runQueue.calls.mostRecent().args[0].queueableFns) {
|
||||
fn.fn();
|
||||
}
|
||||
|
||||
expect(reporter.foo).toHaveBeenCalledWith(event);
|
||||
expect(anotherReporter.foo).toHaveBeenCalledWith(event);
|
||||
const receivedEvents = [reporter, anotherReporter].map(function(reporter) {
|
||||
return reporter.foo.calls.mostRecent().args[0];
|
||||
});
|
||||
expect(receivedEvents[0]).not.toBe(event);
|
||||
expect(receivedEvents[0]).not.toBe(receivedEvents[1]);
|
||||
expect(receivedEvents[0].child).not.toBe(event.child);
|
||||
expect(receivedEvents[0].child).not.toBe(receivedEvents[1].child);
|
||||
});
|
||||
|
||||
it("does not dispatch to a reporter if the reporter doesn't accept the method", function() {
|
||||
const queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(
|
||||
['foo'],
|
||||
queueRunnerFactory
|
||||
),
|
||||
const runQueue = jasmine.createSpy('runQueue'),
|
||||
dispatcher = new privateUnderTest.ReportDispatcher(['foo'], runQueue),
|
||||
reporter = jasmine.createSpyObj('reporter', ['baz']);
|
||||
|
||||
dispatcher.addReporter(reporter);
|
||||
|
||||
dispatcher.foo(123, 456);
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: []
|
||||
})
|
||||
@@ -86,93 +115,90 @@ describe('ReportDispatcher', function() {
|
||||
});
|
||||
|
||||
it("allows providing a fallback reporter in case there's no other reporter", function() {
|
||||
const queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(
|
||||
const runQueue = jasmine.createSpy('runQueue'),
|
||||
dispatcher = new privateUnderTest.ReportDispatcher(
|
||||
['foo', 'bar'],
|
||||
queueRunnerFactory
|
||||
runQueue
|
||||
),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']);
|
||||
|
||||
dispatcher.provideFallbackReporter(reporter);
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
dispatcher.foo({ an: 'event' });
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
isReporter: true
|
||||
})
|
||||
);
|
||||
|
||||
const fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
const fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(reporter.foo).toHaveBeenCalledWith({ an: 'event' });
|
||||
});
|
||||
|
||||
it('does not call fallback reporting methods when another reporter is provided', function() {
|
||||
const queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(
|
||||
const runQueue = jasmine.createSpy('runQueue'),
|
||||
dispatcher = new privateUnderTest.ReportDispatcher(
|
||||
['foo', 'bar'],
|
||||
queueRunnerFactory
|
||||
runQueue
|
||||
),
|
||||
reporter = jasmine.createSpyObj('reporter', ['foo', 'bar']),
|
||||
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
fallbackReporter = jasmine.createSpyObj('otherReporter', ['foo', 'bar']);
|
||||
|
||||
dispatcher.provideFallbackReporter(fallbackReporter);
|
||||
dispatcher.addReporter(reporter);
|
||||
dispatcher.foo(123, 456, completeCallback);
|
||||
dispatcher.foo({ an: 'event' });
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
isReporter: true
|
||||
})
|
||||
);
|
||||
|
||||
const fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
const fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter.foo).toHaveBeenCalledWith(123, 456);
|
||||
expect(fallbackReporter.foo).not.toHaveBeenCalledWith(123, 456);
|
||||
expect(reporter.foo).toHaveBeenCalledWith({ an: 'event' });
|
||||
expect(fallbackReporter.foo).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('allows registered reporters to be cleared', function() {
|
||||
const queueRunnerFactory = jasmine.createSpy('queueRunner'),
|
||||
dispatcher = new jasmineUnderTest.ReportDispatcher(
|
||||
const runQueue = jasmine.createSpy('runQueue'),
|
||||
dispatcher = new privateUnderTest.ReportDispatcher(
|
||||
['foo', 'bar'],
|
||||
queueRunnerFactory
|
||||
runQueue
|
||||
),
|
||||
reporter1 = jasmine.createSpyObj('reporter1', ['foo', 'bar']),
|
||||
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']),
|
||||
completeCallback = jasmine.createSpy('complete');
|
||||
reporter2 = jasmine.createSpyObj('reporter2', ['foo', 'bar']);
|
||||
|
||||
dispatcher.addReporter(reporter1);
|
||||
dispatcher.foo(123, completeCallback);
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
dispatcher.foo({ an: 'event' });
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
isReporter: true
|
||||
})
|
||||
);
|
||||
|
||||
let fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
let fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter1.foo).toHaveBeenCalledWith(123);
|
||||
expect(reporter1.foo).toHaveBeenCalledWith({ an: 'event' });
|
||||
|
||||
dispatcher.clearReporters();
|
||||
dispatcher.addReporter(reporter2);
|
||||
dispatcher.bar(456, completeCallback);
|
||||
dispatcher.bar({ another: 'event' });
|
||||
|
||||
expect(queueRunnerFactory).toHaveBeenCalledWith(
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
isReporter: true
|
||||
})
|
||||
);
|
||||
|
||||
fns = queueRunnerFactory.calls.mostRecent().args[0].queueableFns;
|
||||
fns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
fns[0].fn();
|
||||
expect(reporter1.bar).not.toHaveBeenCalled();
|
||||
expect(reporter2.bar).toHaveBeenCalledWith(456);
|
||||
expect(reporter2.bar).toHaveBeenCalledWith({ another: 'event' });
|
||||
});
|
||||
});
|
||||
|
||||
557
spec/core/RunableResourcesSpec.js
Normal file
557
spec/core/RunableResourcesSpec.js
Normal file
@@ -0,0 +1,557 @@
|
||||
describe('RunableResources', function() {
|
||||
describe('#spies', function() {
|
||||
behavesLikeAPerRunableMutableArray(
|
||||
'spies',
|
||||
'Spies must be created in a before function or a spec',
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
describe('#customSpyStrategies', function() {
|
||||
behavesLikeAPerRunableMutableObject(
|
||||
'customSpyStrategies',
|
||||
'Custom spy strategies must be added in a before function or a spec'
|
||||
);
|
||||
});
|
||||
|
||||
describe('#customEqualityTesters', function() {
|
||||
behavesLikeAPerRunableMutableArray(
|
||||
'customEqualityTesters',
|
||||
'Custom Equalities must be added in a before function or a spec'
|
||||
);
|
||||
});
|
||||
|
||||
describe('#customObjectFormatters', function() {
|
||||
behavesLikeAPerRunableMutableArray(
|
||||
'customObjectFormatters',
|
||||
'Custom object formatters must be added in a before function or a spec'
|
||||
);
|
||||
});
|
||||
|
||||
describe('#customMatchers', function() {
|
||||
behavesLikeAPerRunableMutableObject(
|
||||
'customMatchers',
|
||||
'Matchers must be added in a before function or a spec'
|
||||
);
|
||||
});
|
||||
|
||||
describe('#addCustomMatchers', function() {
|
||||
it("adds all properties to the current runable's matchers", function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
function toBeFoo() {}
|
||||
function toBeBar() {}
|
||||
function toBeBaz() {}
|
||||
|
||||
runableResources.addCustomMatchers({ toBeFoo });
|
||||
expect(runableResources.customMatchers()).toEqual({ toBeFoo });
|
||||
|
||||
runableResources.addCustomMatchers({ toBeBar, toBeBaz });
|
||||
expect(runableResources.customMatchers()).toEqual({
|
||||
toBeFoo,
|
||||
toBeBar,
|
||||
toBeBaz
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#customAsyncMatchers', function() {
|
||||
behavesLikeAPerRunableMutableObject(
|
||||
'customAsyncMatchers',
|
||||
'Async Matchers must be added in a before function or a spec'
|
||||
);
|
||||
});
|
||||
|
||||
describe('#addCustomAsyncMatchers', function() {
|
||||
it("adds all properties to the current runable's matchers", function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
function toBeFoo() {}
|
||||
function toBeBar() {}
|
||||
function toBeBaz() {}
|
||||
|
||||
runableResources.addCustomAsyncMatchers({ toBeFoo });
|
||||
expect(runableResources.customAsyncMatchers()).toEqual({ toBeFoo });
|
||||
|
||||
runableResources.addCustomAsyncMatchers({ toBeBar, toBeBaz });
|
||||
expect(runableResources.customAsyncMatchers()).toEqual({
|
||||
toBeFoo,
|
||||
toBeBar,
|
||||
toBeBaz
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#defaultSpyStrategy', function() {
|
||||
it('returns undefined for a newly initialized resource', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
expect(runableResources.defaultSpyStrategy()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns the value previously set by #setDefaultSpyStrategy', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
const fn = () => {};
|
||||
runableResources.setDefaultSpyStrategy(fn);
|
||||
|
||||
expect(runableResources.defaultSpyStrategy()).toBe(fn);
|
||||
});
|
||||
|
||||
it('is per-runable', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
runableResources.setDefaultSpyStrategy(() => {});
|
||||
currentRunableId = 2;
|
||||
runableResources.initForRunable(2);
|
||||
|
||||
expect(runableResources.defaultSpyStrategy()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('does not require a current runable', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
expect(runableResources.defaultSpyStrategy()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("inherits the parent runable's value", function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
const fn = () => {};
|
||||
runableResources.setDefaultSpyStrategy(fn);
|
||||
currentRunableId = 2;
|
||||
runableResources.initForRunable(2, 1);
|
||||
|
||||
expect(runableResources.defaultSpyStrategy()).toBe(fn);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setDefaultSpyStrategy', function() {
|
||||
it('throws a user-facing error when there is no current runable', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
expect(function() {
|
||||
runableResources.setDefaultSpyStrategy();
|
||||
}).toThrowError(
|
||||
'Default spy strategy must be set in a before function or a spec'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#makePrettyPrinter', function() {
|
||||
it('returns a pretty printer configured with the current customObjectFormatters', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function cof() {}
|
||||
runableResources.customObjectFormatters().push(cof);
|
||||
spyOn(privateUnderTest, 'makePrettyPrinter').and.callThrough();
|
||||
const pp = runableResources.makePrettyPrinter();
|
||||
|
||||
expect(privateUnderTest.makePrettyPrinter).toHaveBeenCalledOnceWith([
|
||||
cof
|
||||
]);
|
||||
expect(pp).toBe(
|
||||
privateUnderTest.makePrettyPrinter.calls.first().returnValue
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#makeMatchersUtil', function() {
|
||||
describe('When there is a current runable', function() {
|
||||
it('returns a MatchersUtil configured with the current resources', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function cof() {}
|
||||
runableResources.customObjectFormatters().push(cof);
|
||||
function ceq() {}
|
||||
runableResources.customEqualityTesters().push(ceq);
|
||||
const expectedPP = {};
|
||||
const expectedMatchersUtil = {};
|
||||
spyOn(privateUnderTest, 'makePrettyPrinter').and.returnValue(
|
||||
expectedPP
|
||||
);
|
||||
spyOn(privateUnderTest, 'MatchersUtil').and.returnValue(
|
||||
expectedMatchersUtil
|
||||
);
|
||||
|
||||
const matchersUtil = runableResources.makeMatchersUtil();
|
||||
|
||||
expect(matchersUtil).toBe(expectedMatchersUtil);
|
||||
expect(privateUnderTest.makePrettyPrinter).toHaveBeenCalledOnceWith([
|
||||
cof
|
||||
]);
|
||||
// We need === equality on the pp passed to MatchersUtil
|
||||
expect(privateUnderTest.MatchersUtil).toHaveBeenCalledOnceWith(
|
||||
jasmine.objectContaining({
|
||||
customTesters: [ceq]
|
||||
})
|
||||
);
|
||||
expect(privateUnderTest.MatchersUtil.calls.argsFor(0)[0].pp).toBe(
|
||||
expectedPP
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When there is no current runable', function() {
|
||||
it('returns a MatchersUtil configured with defaults', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
const expectedMatchersUtil = {};
|
||||
spyOn(privateUnderTest, 'MatchersUtil').and.returnValue(
|
||||
expectedMatchersUtil
|
||||
);
|
||||
|
||||
const matchersUtil = runableResources.makeMatchersUtil();
|
||||
|
||||
expect(matchersUtil).toBe(expectedMatchersUtil);
|
||||
// We need === equality on the pp passed to MatchersUtil
|
||||
expect(privateUnderTest.MatchersUtil).toHaveBeenCalledTimes(1);
|
||||
expect(privateUnderTest.MatchersUtil.calls.argsFor(0)[0].pp).toBe(
|
||||
privateUnderTest.basicPrettyPrinter
|
||||
);
|
||||
expect(
|
||||
privateUnderTest.MatchersUtil.calls.argsFor(0)[0].customTesters
|
||||
).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('.spyFactory', function() {
|
||||
describe('When there is no current runable', function() {
|
||||
it('is configured with default strategies and matchersUtil', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
spyOn(privateUnderTest, 'Spy');
|
||||
const matchersUtil = {};
|
||||
spyOn(runableResources, 'makeMatchersUtil').and.returnValue(
|
||||
matchersUtil
|
||||
);
|
||||
|
||||
runableResources.spyFactory.createSpy('foo');
|
||||
|
||||
expect(privateUnderTest.Spy).toHaveBeenCalledWith(
|
||||
'foo',
|
||||
is(matchersUtil),
|
||||
jasmine.objectContaining({
|
||||
customStrategies: {},
|
||||
defaultStrategyFn: undefined
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When there is a current runable', function() {
|
||||
it("is configured with the current runable's strategies and matchersUtil", function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function customStrategy() {}
|
||||
function defaultStrategy() {}
|
||||
runableResources.customSpyStrategies().foo = customStrategy;
|
||||
runableResources.setDefaultSpyStrategy(defaultStrategy);
|
||||
spyOn(privateUnderTest, 'Spy');
|
||||
const matchersUtil = {};
|
||||
spyOn(runableResources, 'makeMatchersUtil').and.returnValue(
|
||||
matchersUtil
|
||||
);
|
||||
|
||||
runableResources.spyFactory.createSpy('foo');
|
||||
|
||||
expect(privateUnderTest.Spy).toHaveBeenCalledWith(
|
||||
'foo',
|
||||
is(matchersUtil),
|
||||
jasmine.objectContaining({
|
||||
customStrategies: { foo: customStrategy },
|
||||
defaultStrategyFn: defaultStrategy
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function is(expected) {
|
||||
return {
|
||||
asymmetricMatch: function(actual) {
|
||||
return actual === expected;
|
||||
},
|
||||
jasmineToString: function(pp) {
|
||||
return '<same instance as ' + pp(expected) + '>';
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
describe('.spyRegistry', function() {
|
||||
it("writes to the current runable's spies", function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function foo() {}
|
||||
const spyObj = { foo };
|
||||
runableResources.spyRegistry.spyOn(spyObj, 'foo');
|
||||
|
||||
expect(runableResources.spies()).toEqual([
|
||||
jasmine.objectContaining({
|
||||
restoreObjectToOriginalState: jasmine.any(Function)
|
||||
})
|
||||
]);
|
||||
expect(jasmineUnderTest.isSpy(spyObj.foo)).toBeTrue();
|
||||
|
||||
runableResources.spyRegistry.clearSpies();
|
||||
expect(spyObj.foo).toBe(foo);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#clearForRunable', function() {
|
||||
it('removes resources for the specified runable', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
expect(function() {
|
||||
runableResources.spies();
|
||||
}).not.toThrow();
|
||||
runableResources.clearForRunable(1);
|
||||
expect(function() {
|
||||
runableResources.spies();
|
||||
}).toThrowError('Spies must be created in a before function or a spec');
|
||||
});
|
||||
|
||||
it('clears spies', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function foo() {}
|
||||
const spyObj = { foo };
|
||||
runableResources.spyRegistry.spyOn(spyObj, 'foo');
|
||||
expect(spyObj.foo).not.toBe(foo);
|
||||
|
||||
runableResources.clearForRunable(1);
|
||||
expect(spyObj.foo).toBe(foo);
|
||||
});
|
||||
|
||||
it('clears the global error spy', function() {
|
||||
const globalErrors = jasmine.createSpyObj('globalErrors', [
|
||||
'removeOverrideListener'
|
||||
]);
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
getCurrentRunableId: () => 1,
|
||||
globalErrors
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
runableResources.clearForRunable(1);
|
||||
expect(globalErrors.removeOverrideListener).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('does not remove resources for other runables', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => 1
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function cof() {}
|
||||
runableResources.customObjectFormatters().push(cof);
|
||||
runableResources.clearForRunable(2);
|
||||
expect(runableResources.customObjectFormatters()).toEqual([cof]);
|
||||
});
|
||||
});
|
||||
|
||||
function behavesLikeAPerRunableMutableArray(
|
||||
methodName,
|
||||
errorMsg,
|
||||
inherits = true
|
||||
) {
|
||||
it('is initially empty', function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
expect(runableResources[methodName]()).toEqual([]);
|
||||
});
|
||||
|
||||
it('is mutable', function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function newItem() {}
|
||||
runableResources[methodName]().push(newItem);
|
||||
expect(runableResources[methodName]()).toEqual([newItem]);
|
||||
});
|
||||
|
||||
it('is per-runable', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
runableResources[methodName]().push(() => {});
|
||||
runableResources.initForRunable(2);
|
||||
currentRunableId = 2;
|
||||
expect(runableResources[methodName]()).toEqual([]);
|
||||
});
|
||||
|
||||
it('throws a user-facing error when there is no current runable', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
expect(function() {
|
||||
runableResources[methodName]();
|
||||
}).toThrowError(errorMsg);
|
||||
});
|
||||
|
||||
if (inherits) {
|
||||
it('inherits from the parent runable', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function parentItem() {}
|
||||
runableResources[methodName]().push(parentItem);
|
||||
runableResources.initForRunable(2, 1);
|
||||
currentRunableId = 2;
|
||||
function childItem() {}
|
||||
runableResources[methodName]().push(childItem);
|
||||
expect(runableResources[methodName]()).toEqual([parentItem, childItem]);
|
||||
|
||||
currentRunableId = 1;
|
||||
expect(runableResources[methodName]()).toEqual([parentItem]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function behavesLikeAPerRunableMutableObject(methodName, errorMsg) {
|
||||
it('is initially empty', function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
|
||||
expect(runableResources[methodName]()).toEqual({});
|
||||
});
|
||||
|
||||
it('is mutable', function() {
|
||||
const currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function newItem() {}
|
||||
runableResources[methodName]().foo = newItem;
|
||||
expect(runableResources[methodName]()).toEqual({ foo: newItem });
|
||||
});
|
||||
|
||||
it('is per-runable', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
runableResources[methodName]().foo = function() {};
|
||||
runableResources.initForRunable(2);
|
||||
currentRunableId = 2;
|
||||
expect(runableResources[methodName]()).toEqual({});
|
||||
});
|
||||
|
||||
it('throws a user-facing error when there is no current runable', function() {
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => null
|
||||
});
|
||||
expect(function() {
|
||||
runableResources[methodName]();
|
||||
}).toThrowError(errorMsg);
|
||||
});
|
||||
|
||||
it('inherits from the parent runable', function() {
|
||||
let currentRunableId = 1;
|
||||
const runableResources = new privateUnderTest.RunableResources({
|
||||
globalErrors: stubGlobalErrors(),
|
||||
getCurrentRunableId: () => currentRunableId
|
||||
});
|
||||
runableResources.initForRunable(1);
|
||||
function parentItem() {}
|
||||
runableResources[methodName]().parentName = parentItem;
|
||||
runableResources.initForRunable(2, 1);
|
||||
currentRunableId = 2;
|
||||
function childItem() {}
|
||||
runableResources[methodName]().childName = childItem;
|
||||
expect(runableResources[methodName]()).toEqual({
|
||||
parentName: parentItem,
|
||||
childName: childItem
|
||||
});
|
||||
|
||||
currentRunableId = 1;
|
||||
expect(runableResources[methodName]()).toEqual({
|
||||
parentName: parentItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function stubGlobalErrors() {
|
||||
return {
|
||||
removeOverrideListener() {}
|
||||
};
|
||||
}
|
||||
});
|
||||
499
spec/core/RunnerSpec.js
Normal file
499
spec/core/RunnerSpec.js
Normal file
@@ -0,0 +1,499 @@
|
||||
describe('Runner', function() {
|
||||
describe('Integration with TreeProcessor and TreeRunner', function() {
|
||||
let suiteNumber,
|
||||
specNumber,
|
||||
runQueue,
|
||||
globalErrors,
|
||||
reportDispatcher,
|
||||
failSpecWithNoExpectations,
|
||||
detectLateRejectionHandling;
|
||||
|
||||
beforeEach(function() {
|
||||
suiteNumber = 0;
|
||||
specNumber = 0;
|
||||
runQueue = jasmine.createSpy('runQueue');
|
||||
globalErrors = 'the global errors instance';
|
||||
reportDispatcher = jasmine.createSpyObj(
|
||||
'reportDispatcher',
|
||||
privateUnderTest.reporterEvents
|
||||
);
|
||||
|
||||
for (const k of privateUnderTest.reporterEvents) {
|
||||
reportDispatcher[k].and.returnValue(Promise.resolve());
|
||||
}
|
||||
|
||||
// Reasonable defaults, may be overridden in some cases
|
||||
failSpecWithNoExpectations = false;
|
||||
detectLateRejectionHandling = false;
|
||||
|
||||
spyOn(privateUnderTest.TreeRunner.prototype, '_executeSpec');
|
||||
});
|
||||
|
||||
function StubSuite(attrs) {
|
||||
attrs = attrs || {};
|
||||
this.id = 'suite' + suiteNumber++;
|
||||
this.children = attrs.children || [];
|
||||
this.canBeReentered = function() {
|
||||
return !attrs.noReenter;
|
||||
};
|
||||
this.markedPending = attrs.markedPending || false;
|
||||
this.sharedUserContext = function() {
|
||||
return attrs.userContext || {};
|
||||
};
|
||||
this.result = {
|
||||
id: this.id,
|
||||
failedExpectations: []
|
||||
};
|
||||
this.getResult = jasmine.createSpy('getResult');
|
||||
this.beforeAllFns = attrs.beforeAllFns || [];
|
||||
this.afterAllFns = attrs.afterAllFns || [];
|
||||
this.cleanupBeforeAfter = function() {};
|
||||
this.startTimer = function() {};
|
||||
this.endTimer = function() {};
|
||||
}
|
||||
|
||||
function StubSpec(attrs) {
|
||||
attrs = attrs || {};
|
||||
this.id = 'spec' + specNumber++;
|
||||
this.markedPending = attrs.markedPending || false;
|
||||
this.execute = jasmine.createSpy(this.id + '#execute');
|
||||
this.beforeAndAfterFns = () => ({ befores: [], afters: [] });
|
||||
this.userContext = () => ({});
|
||||
this.getFullName = () => '';
|
||||
this.queueableFn = () => {};
|
||||
}
|
||||
|
||||
function makeRunner(topSuite) {
|
||||
const defaultOptions = {
|
||||
getConfig: () => ({
|
||||
specFilter: () => true,
|
||||
failSpecWithNoExpectations,
|
||||
detectLateRejectionHandling
|
||||
}),
|
||||
focusedRunables: () => [],
|
||||
totalSpecsDefined: () => 1,
|
||||
TreeProcessor: privateUnderTest.TreeProcessor,
|
||||
runableResources: {
|
||||
initForRunable: () => {},
|
||||
clearForRunable: () => {}
|
||||
},
|
||||
reportDispatcher,
|
||||
globalErrors,
|
||||
runQueue
|
||||
};
|
||||
return new privateUnderTest.Runner({
|
||||
...defaultOptions,
|
||||
topSuite
|
||||
});
|
||||
}
|
||||
|
||||
function arrayNotContaining(item) {
|
||||
return {
|
||||
asymmetricMatch(other, matchersUtil) {
|
||||
if (!jasmine.private.isArray(other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const x of other) {
|
||||
if (matchersUtil.equals(x, item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Precondition: privateUnderTest.TreeRunner.prototype._executeSpec is a spy
|
||||
function verifyAndFinishSpec(spec, queueableFn, shouldBeExcluded) {
|
||||
const ex = privateUnderTest.TreeRunner.prototype._executeSpec;
|
||||
ex.withArgs(spec, 'onComplete').and.callThrough();
|
||||
|
||||
queueableFn.fn('onComplete');
|
||||
expect(ex).toHaveBeenCalledWith(spec, 'onComplete');
|
||||
|
||||
expect(runQueue).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
isLeaf: true,
|
||||
SkipPolicy: privateUnderTest.CompleteOnFirstErrorSkipPolicy,
|
||||
queueableFns: shouldBeExcluded
|
||||
? arrayNotContaining(spec.queueableFn)
|
||||
: jasmine.arrayContaining([spec.queueableFn])
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
it('runs a single spec', async function() {
|
||||
const spec = new StubSpec();
|
||||
const topSuite = new StubSuite({
|
||||
children: [spec],
|
||||
userContext: { root: 'context' }
|
||||
});
|
||||
detectLateRejectionHandling = true;
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
|
||||
expect(runQueue).toHaveBeenCalledWith({
|
||||
onComplete: jasmine.any(Function),
|
||||
onException: jasmine.any(Function),
|
||||
userContext: { root: 'context' },
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
onMultipleDone: null,
|
||||
SkipPolicy: privateUnderTest.SkipAfterBeforeAllErrorPolicy
|
||||
});
|
||||
|
||||
const runQueueArgs = runQueue.calls.mostRecent().args[0];
|
||||
verifyAndFinishSpec(spec, runQueueArgs.queueableFns[0], false);
|
||||
runQueueArgs.onComplete();
|
||||
await promise;
|
||||
});
|
||||
|
||||
it('runs an empty suite', async function() {
|
||||
const suite = new StubSuite({ userContext: { for: 'suite' } });
|
||||
const topSuite = new StubSuite({
|
||||
children: [suite],
|
||||
userContext: { for: 'topSuite' }
|
||||
});
|
||||
suite.parentSuite = topSuite;
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
|
||||
expect(runQueue).toHaveBeenCalledWith({
|
||||
onComplete: jasmine.any(Function),
|
||||
onException: jasmine.any(Function),
|
||||
userContext: { for: 'topSuite' },
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
onMultipleDone: null,
|
||||
SkipPolicy: privateUnderTest.SkipAfterBeforeAllErrorPolicy
|
||||
});
|
||||
|
||||
const runQueueArgs = runQueue.calls.mostRecent().args[0];
|
||||
const nodeDone = jasmine.createSpy('nodeDone');
|
||||
runQueueArgs.queueableFns[0].fn(nodeDone);
|
||||
expect(runQueue).toHaveBeenCalledWith({
|
||||
onComplete: jasmine.any(Function),
|
||||
onMultipleDone: null,
|
||||
queueableFns: [{ fn: jasmine.any(Function) }],
|
||||
userContext: { for: 'suite' },
|
||||
onException: jasmine.any(Function),
|
||||
onMultipleDone: null,
|
||||
SkipPolicy: privateUnderTest.SkipAfterBeforeAllErrorPolicy
|
||||
});
|
||||
|
||||
runQueue.calls.mostRecent().args[0].queueableFns[0].fn('foo');
|
||||
expect(reportDispatcher.suiteStarted).toHaveBeenCalledWith(suite.result);
|
||||
|
||||
suite.getResult.and.returnValue({ my: 'result' });
|
||||
|
||||
runQueue.calls.mostRecent().args[0].onComplete();
|
||||
expect(reportDispatcher.suiteDone).toHaveBeenCalledWith({ my: 'result' });
|
||||
|
||||
runQueueArgs.onComplete();
|
||||
await promise;
|
||||
});
|
||||
|
||||
it('runs a non-empty suite', async function() {
|
||||
const spec1 = new StubSpec();
|
||||
const spec2 = new StubSpec();
|
||||
const suite = new StubSuite({ children: [spec1, spec2] });
|
||||
const topSuite = new StubSuite({ children: [suite] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
let queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
expect(runQueue).toHaveBeenCalledTimes(2);
|
||||
queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(3);
|
||||
|
||||
verifyAndFinishSpec(spec1, queueableFns[1], false);
|
||||
verifyAndFinishSpec(spec2, queueableFns[2], false);
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('"runs" an excluded suite', async function() {
|
||||
const spec = new StubSpec();
|
||||
const parent = new StubSuite({ children: [spec] });
|
||||
const topSuite = new StubSuite({ children: [parent] });
|
||||
parent.parentSuite = topSuite;
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
// Empty list of runable IDs excludes everything
|
||||
const promise = subject.execute([]);
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
let queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(2);
|
||||
|
||||
queueableFns[0].fn();
|
||||
expect(reportDispatcher.suiteStarted).toHaveBeenCalledWith(parent.result);
|
||||
|
||||
verifyAndFinishSpec(spec, queueableFns[1], true);
|
||||
|
||||
parent.getResult.and.returnValue(parent.result);
|
||||
runQueue.calls.argsFor(1)[0].onComplete();
|
||||
expect(reportDispatcher.suiteDone).toHaveBeenCalledWith(parent.result);
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('handles the failSpecWithNoExpectations option', async function() {
|
||||
failSpecWithNoExpectations = true;
|
||||
const spec = new StubSpec();
|
||||
const parent = new StubSuite({ children: [spec] });
|
||||
const topSuite = new StubSuite({ children: [parent] });
|
||||
parent.parentSuite = topSuite;
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
let queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(2);
|
||||
|
||||
queueableFns[1].fn('foo');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(spec, 'foo');
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs beforeAlls and afterAlls for a suite with children', async function() {
|
||||
const spec = new StubSpec();
|
||||
const target = new StubSuite({
|
||||
children: [spec],
|
||||
beforeAllFns: [
|
||||
{ fn: 'beforeAll1', timeout: 1 },
|
||||
{ fn: 'beforeAll2', timeout: 2 }
|
||||
],
|
||||
afterAllFns: [
|
||||
{ fn: 'afterAll1', timeout: 3 },
|
||||
{ fn: 'afterAll2', timeout: 4 }
|
||||
]
|
||||
});
|
||||
const topSuite = new StubSuite({ children: [target] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
expect(runQueue.calls.mostRecent().args[0].queueableFns).toEqual([
|
||||
{ fn: jasmine.any(Function) },
|
||||
{ fn: 'beforeAll1', timeout: 1 },
|
||||
{ fn: 'beforeAll2', timeout: 2 },
|
||||
{ fn: jasmine.any(Function) },
|
||||
{ fn: 'afterAll1', timeout: 3 },
|
||||
{ fn: 'afterAll2', timeout: 4 }
|
||||
]);
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('does not run beforeAlls or afterAlls for a suite with no children', async function() {
|
||||
const target = new StubSuite({
|
||||
beforeAllFns: [{ fn: 'before' }],
|
||||
afterAllFns: [{ fn: 'after' }]
|
||||
});
|
||||
const topSuite = new StubSuite({ children: [target] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
expect(runQueue.calls.mostRecent().args[0].queueableFns.length).toEqual(
|
||||
1
|
||||
);
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('does not run beforeAlls or afterAlls for a suite with only pending children', async function() {
|
||||
const spec = new StubSpec({ markedPending: true });
|
||||
const target = new StubSuite({
|
||||
children: [spec],
|
||||
beforeAllFns: [{ fn: 'before' }],
|
||||
afterAllFns: [{ fn: 'after' }]
|
||||
});
|
||||
const topSuite = new StubSuite({ children: [target] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn(function() {});
|
||||
|
||||
expect(runQueue.calls.mostRecent().args[0].queueableFns.length).toEqual(
|
||||
2
|
||||
);
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs specs in the order specified', async function() {
|
||||
const specs = [new StubSpec(), new StubSpec()];
|
||||
const topSuite = new StubSuite({ children: specs });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute([specs[1].id, specs[0].id]);
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn('done');
|
||||
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).not.toHaveBeenCalledWith(specs[0], jasmine.anything());
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(specs[1], 'done');
|
||||
|
||||
queueableFns[1].fn('done');
|
||||
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(specs[0], 'done');
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs specified specs before non-specified specs within a suite', async function() {
|
||||
const specified = new StubSpec();
|
||||
const nonSpecified = new StubSpec();
|
||||
const topSuite = new StubSuite({ children: [nonSpecified, specified] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute([specified.id]);
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn('done');
|
||||
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).not.toHaveBeenCalledWith(nonSpecified, jasmine.anything());
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(specified, 'done');
|
||||
|
||||
queueableFns[1].fn('done');
|
||||
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(nonSpecified, 'done');
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs suites and specs with a specified order', async function() {
|
||||
const specifiedSpec = new StubSpec();
|
||||
const nonSpecifiedSpec = new StubSpec();
|
||||
const specifiedSuite = new StubSuite({ children: [nonSpecifiedSpec] });
|
||||
const topSuite = new StubSuite({
|
||||
children: [specifiedSpec, specifiedSuite]
|
||||
});
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute([specifiedSuite.id, specifiedSpec.id]);
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
queueableFns[0].fn();
|
||||
|
||||
expect(specifiedSpec.execute).not.toHaveBeenCalled();
|
||||
const nodeQueueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
nodeQueueableFns[1].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(nonSpecifiedSpec, 'done');
|
||||
|
||||
queueableFns[1].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(specifiedSpec, 'done');
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs suites and specs in the order they were declared', async function() {
|
||||
const spec1 = new StubSpec();
|
||||
const spec2 = new StubSpec();
|
||||
const spec3 = new StubSpec();
|
||||
const parent = new StubSuite({ children: [spec2, spec3] });
|
||||
const topSuite = new StubSuite({ children: [spec1, parent] });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(2);
|
||||
|
||||
queueableFns[0].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(spec1, 'done');
|
||||
|
||||
queueableFns[1].fn();
|
||||
const childFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(childFns.length).toBe(3);
|
||||
childFns[1].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(spec2, 'done');
|
||||
|
||||
childFns[2].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(spec3, 'done');
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
|
||||
it('runs large segments of nodes in the order they were declared', async function() {
|
||||
const specs = [];
|
||||
|
||||
for (let i = 0; i < 11; i++) {
|
||||
specs.push(new StubSpec());
|
||||
}
|
||||
|
||||
const topSuite = new StubSuite({ children: specs });
|
||||
const subject = makeRunner(topSuite);
|
||||
|
||||
const promise = subject.execute();
|
||||
await Promise.resolve();
|
||||
expect(runQueue).toHaveBeenCalledTimes(1);
|
||||
const queueableFns = runQueue.calls.mostRecent().args[0].queueableFns;
|
||||
expect(queueableFns.length).toBe(11);
|
||||
|
||||
for (let i = 0; i < 11; i++) {
|
||||
queueableFns[i].fn('done');
|
||||
expect(
|
||||
privateUnderTest.TreeRunner.prototype._executeSpec
|
||||
).toHaveBeenCalledWith(specs[i], 'done');
|
||||
}
|
||||
|
||||
await expectAsync(promise).toBePending();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,7 +2,7 @@ describe('SkipAfterBeforeAllErrorPolicy', function() {
|
||||
describe('#skipTo', function() {
|
||||
describe('When nothing has errored', function() {
|
||||
it('does not skip anything', function() {
|
||||
const policy = new jasmineUnderTest.SkipAfterBeforeAllErrorPolicy(
|
||||
const policy = new privateUnderTest.SkipAfterBeforeAllErrorPolicy(
|
||||
arrayOfArbitraryFns(4)
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('SkipAfterBeforeAllErrorPolicy', function() {
|
||||
|
||||
describe('When anything but a beforeAll has errored', function() {
|
||||
it('does not skip anything', function() {
|
||||
const policy = new jasmineUnderTest.SkipAfterBeforeAllErrorPolicy(
|
||||
const policy = new privateUnderTest.SkipAfterBeforeAllErrorPolicy(
|
||||
arrayOfArbitraryFns(4)
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ describe('SkipAfterBeforeAllErrorPolicy', function() {
|
||||
{ type: 'afterAll', fn: () => {} },
|
||||
{ type: 'afterAll', fn: () => {} }
|
||||
];
|
||||
const policy = new jasmineUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
const policy = new privateUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
|
||||
policy.fnErrored(0);
|
||||
expect(policy.skipTo(0)).toEqual(3);
|
||||
@@ -54,7 +54,7 @@ describe('SkipAfterBeforeAllErrorPolicy', function() {
|
||||
it("sets the suite's hadBeforeAllFailure property to true", function() {
|
||||
const suite = {};
|
||||
const fns = [{ type: 'beforeAll', fn: () => {}, suite }];
|
||||
const policy = new jasmineUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
const policy = new privateUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
|
||||
policy.fnErrored(0);
|
||||
|
||||
@@ -65,7 +65,7 @@ describe('SkipAfterBeforeAllErrorPolicy', function() {
|
||||
describe('When the fn is not a beforeAll', function() {
|
||||
it('does not try to access the suite, which is probably not there', function() {
|
||||
const fns = [{ fn: () => {} /* no suite */ }];
|
||||
const policy = new jasmineUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
const policy = new privateUnderTest.SkipAfterBeforeAllErrorPolicy(fns);
|
||||
|
||||
expect(() => policy.fnErrored(0)).not.toThrow();
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
describe('SpyRegistry', function() {
|
||||
function createSpy(name, originalFn) {
|
||||
return jasmineUnderTest.Spy(name, originalFn);
|
||||
return privateUnderTest.Spy(name, originalFn);
|
||||
}
|
||||
|
||||
describe('#spyOn', function() {
|
||||
it('checks for the existence of the object', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
});
|
||||
expect(function() {
|
||||
@@ -14,53 +14,53 @@ describe('SpyRegistry', function() {
|
||||
});
|
||||
|
||||
it('checks that a method name was passed', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(subject);
|
||||
spyRegistry.spyOn(target);
|
||||
}).toThrowError(/No method name supplied/);
|
||||
});
|
||||
|
||||
it('checks that the object is not `null`', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry();
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(null, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
});
|
||||
|
||||
it('checks that the method name is not `null`', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(subject, null);
|
||||
spyRegistry.spyOn(target, null);
|
||||
}).toThrowError(/No method name supplied/);
|
||||
});
|
||||
|
||||
it('checks for the existence of the method', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(subject, 'pants');
|
||||
spyRegistry.spyOn(target, 'pants');
|
||||
}).toThrowError(/method does not exist/);
|
||||
});
|
||||
|
||||
it('checks if it has already been spied upon', function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = { spiedFunc: function() {} };
|
||||
target = { spiedFunc: function() {} };
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
}).toThrowError(/has already been spied upon/);
|
||||
});
|
||||
|
||||
@@ -78,72 +78,108 @@ describe('SpyRegistry', function() {
|
||||
});
|
||||
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
}
|
||||
}),
|
||||
subject = { spiedFunc: scope.myFunc };
|
||||
target = { spiedFunc: scope.myFunc };
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(scope, 'myFunc');
|
||||
}).toThrowError(/is not declared writable or has no setter/);
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
}).not.toThrowError(/is not declared writable or has no setter/);
|
||||
});
|
||||
|
||||
it('throws if assigning to the property is a no-op', function() {
|
||||
const scope = {};
|
||||
|
||||
function original() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Object.defineProperty(scope, 'myFunc', {
|
||||
get() {
|
||||
return original;
|
||||
},
|
||||
set() {}
|
||||
});
|
||||
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
});
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(scope, 'myFunc');
|
||||
}).toThrowError(
|
||||
"<spyOn> : Can't spy on myFunc because assigning to it had no effect"
|
||||
);
|
||||
});
|
||||
|
||||
it('overrides the method on the object and returns the spy', function() {
|
||||
const originalFunctionWasCalled = false,
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = {
|
||||
spiedFunc: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
let originalFunctionWasCalled = false;
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
});
|
||||
const target = {
|
||||
spiedFunc: function() {
|
||||
originalFunctionWasCalled = true;
|
||||
}
|
||||
};
|
||||
|
||||
const spy = spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
const spy = spyRegistry.spyOn(target, 'spiedFunc');
|
||||
|
||||
expect(subject.spiedFunc).toEqual(spy);
|
||||
subject.spiedFunc();
|
||||
expect(target.spiedFunc).toEqual(spy);
|
||||
target.spiedFunc();
|
||||
expect(originalFunctionWasCalled).toBe(false);
|
||||
});
|
||||
|
||||
it('throws if the method is a mock clock method', function() {
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
});
|
||||
const target = { spiedFunc: function() {} };
|
||||
target.spiedFunc[privateUnderTest.Clock.IsMockClockTimingFn] = true;
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
}).toThrowError("Mock clock timing functions can't be spied on");
|
||||
});
|
||||
});
|
||||
|
||||
describe('#spyOnProperty', function() {
|
||||
it('checks for the existence of the object', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry();
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(void 0, 'pants');
|
||||
}).toThrowError(/could not find an object/);
|
||||
});
|
||||
|
||||
it('checks that a property name was passed', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject);
|
||||
spyRegistry.spyOnProperty(target);
|
||||
}).toThrowError(/No property name supplied/);
|
||||
});
|
||||
|
||||
it('checks for the existence of the method', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject, 'pants');
|
||||
spyRegistry.spyOnProperty(target, 'pants');
|
||||
}).toThrowError(/property does not exist/);
|
||||
});
|
||||
|
||||
it('checks for the existence of access type', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry(),
|
||||
subject = {};
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry(),
|
||||
target = {};
|
||||
|
||||
Object.defineProperty(subject, 'pants', {
|
||||
Object.defineProperty(target, 'pants', {
|
||||
get: function() {
|
||||
return 1;
|
||||
},
|
||||
@@ -151,65 +187,65 @@ describe('SpyRegistry', function() {
|
||||
});
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject, 'pants', 'set');
|
||||
spyRegistry.spyOnProperty(target, 'pants', 'set');
|
||||
}).toThrowError(/does not have access type/);
|
||||
});
|
||||
|
||||
it('checks if it can be spied upon', function() {
|
||||
const subject = {};
|
||||
const target = {};
|
||||
|
||||
Object.defineProperty(subject, 'myProp', {
|
||||
Object.defineProperty(target, 'myProp', {
|
||||
get: function() {}
|
||||
});
|
||||
|
||||
Object.defineProperty(subject, 'spiedProp', {
|
||||
Object.defineProperty(target, 'spiedProp', {
|
||||
get: function() {},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry();
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject, 'myProp');
|
||||
spyRegistry.spyOnProperty(target, 'myProp');
|
||||
}).toThrowError(/is not declared configurable/);
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
}).not.toThrowError(/is not declared configurable/);
|
||||
});
|
||||
|
||||
it('overrides the property getter on the object and returns the spy', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = {},
|
||||
target = {},
|
||||
returnValue = 1;
|
||||
|
||||
Object.defineProperty(subject, 'spiedProperty', {
|
||||
Object.defineProperty(target, 'spiedProperty', {
|
||||
get: function() {
|
||||
return returnValue;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
expect(subject.spiedProperty).toEqual(returnValue);
|
||||
expect(target.spiedProperty).toEqual(returnValue);
|
||||
|
||||
const spy = spyRegistry.spyOnProperty(subject, 'spiedProperty');
|
||||
const getter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty')
|
||||
const spy = spyRegistry.spyOnProperty(target, 'spiedProperty');
|
||||
const getter = Object.getOwnPropertyDescriptor(target, 'spiedProperty')
|
||||
.get;
|
||||
|
||||
expect(getter).toEqual(spy);
|
||||
expect(subject.spiedProperty).toBeUndefined();
|
||||
expect(target.spiedProperty).toBeUndefined();
|
||||
});
|
||||
|
||||
it('overrides the property setter on the object and returns the spy', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = {},
|
||||
target = {},
|
||||
returnValue = 1;
|
||||
|
||||
Object.defineProperty(subject, 'spiedProperty', {
|
||||
Object.defineProperty(target, 'spiedProperty', {
|
||||
get: function() {
|
||||
return returnValue;
|
||||
},
|
||||
@@ -217,53 +253,53 @@ describe('SpyRegistry', function() {
|
||||
configurable: true
|
||||
});
|
||||
|
||||
const spy = spyRegistry.spyOnProperty(subject, 'spiedProperty', 'set');
|
||||
const setter = Object.getOwnPropertyDescriptor(subject, 'spiedProperty')
|
||||
const spy = spyRegistry.spyOnProperty(target, 'spiedProperty', 'set');
|
||||
const setter = Object.getOwnPropertyDescriptor(target, 'spiedProperty')
|
||||
.set;
|
||||
|
||||
expect(subject.spiedProperty).toEqual(returnValue);
|
||||
expect(target.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() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = {};
|
||||
target = {};
|
||||
|
||||
Object.defineProperty(subject, 'spiedProp', {
|
||||
Object.defineProperty(target, 'spiedProp', {
|
||||
get: function() {
|
||||
return 1;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
|
||||
expect(function() {
|
||||
spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
}).toThrowError(/spiedProp#get has already been spied upon/);
|
||||
});
|
||||
|
||||
it('returns the original spy if respy is allowed', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: createSpy
|
||||
}),
|
||||
subject = {};
|
||||
target = {};
|
||||
|
||||
spyRegistry.allowRespy(true);
|
||||
|
||||
Object.defineProperty(subject, 'spiedProp', {
|
||||
Object.defineProperty(target, 'spiedProp', {
|
||||
get: function() {
|
||||
return 1;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
const originalSpy = spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
const originalSpy = spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
|
||||
expect(spyRegistry.spyOnProperty(subject, 'spiedProp')).toBe(
|
||||
expect(spyRegistry.spyOnProperty(target, 'spiedProp')).toBe(
|
||||
originalSpy
|
||||
);
|
||||
});
|
||||
@@ -272,14 +308,14 @@ describe('SpyRegistry', function() {
|
||||
|
||||
describe('#spyOnAllFunctions', function() {
|
||||
it('checks for the existence of the object', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry();
|
||||
const spyRegistry = new privateUnderTest.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() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
@@ -298,21 +334,21 @@ describe('SpyRegistry', function() {
|
||||
const parent = {
|
||||
parentSpied1: noop1
|
||||
};
|
||||
const subject = Object.create(parent);
|
||||
Object.defineProperty(subject, 'spied1', {
|
||||
const target = Object.create(parent);
|
||||
Object.defineProperty(target, 'spied1', {
|
||||
value: noop1,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
Object.defineProperty(subject, 'spied2', {
|
||||
Object.defineProperty(target, 'spied2', {
|
||||
value: noop2,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
let _spied3 = noop3;
|
||||
Object.defineProperty(subject, 'spied3', {
|
||||
Object.defineProperty(target, 'spied3', {
|
||||
configurable: true,
|
||||
set: function(val) {
|
||||
_spied3 = val;
|
||||
@@ -322,20 +358,20 @@ describe('SpyRegistry', function() {
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
subject.spied4 = noop4;
|
||||
Object.defineProperty(subject, 'notSpied2', {
|
||||
target.spied4 = noop4;
|
||||
Object.defineProperty(target, 'notSpied2', {
|
||||
value: noop2,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
Object.defineProperty(subject, 'notSpied3', {
|
||||
Object.defineProperty(target, 'notSpied3', {
|
||||
value: noop3,
|
||||
writable: true,
|
||||
configurable: false,
|
||||
enumerable: true
|
||||
});
|
||||
Object.defineProperty(subject, 'notSpied4', {
|
||||
Object.defineProperty(target, 'notSpied4', {
|
||||
configurable: false,
|
||||
set: function() {
|
||||
/**/
|
||||
@@ -345,31 +381,31 @@ describe('SpyRegistry', function() {
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
Object.defineProperty(subject, 'notSpied5', {
|
||||
Object.defineProperty(target, 'notSpied5', {
|
||||
value: noop5,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: false
|
||||
});
|
||||
subject.notSpied6 = 6;
|
||||
target.notSpied6 = 6;
|
||||
|
||||
const spiedObject = spyRegistry.spyOnAllFunctions(subject);
|
||||
const spiedObject = spyRegistry.spyOnAllFunctions(target);
|
||||
|
||||
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);
|
||||
expect(target.parentSpied1).toBe('I am a spy');
|
||||
expect(target.notSpied2).toBe(noop2);
|
||||
expect(target.notSpied3).toBe(noop3);
|
||||
expect(target.notSpied4).toBe(noop4);
|
||||
expect(target.notSpied5).toBe(noop5);
|
||||
expect(target.notSpied6).toBe(6);
|
||||
expect(target.spied1).toBe('I am a spy');
|
||||
expect(target.spied2).toBe('I am a spy');
|
||||
expect(target.spied3).toBe('I am a spy');
|
||||
expect(target.spied4).toBe('I am a spy');
|
||||
expect(spiedObject).toBe(target);
|
||||
});
|
||||
|
||||
it('overrides prototype methods on the object', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
@@ -383,145 +419,145 @@ describe('SpyRegistry', function() {
|
||||
};
|
||||
MyClass.prototype.spied2 = noop2;
|
||||
|
||||
const subject = new MyClass();
|
||||
spyRegistry.spyOnAllFunctions(subject);
|
||||
const target = new MyClass();
|
||||
spyRegistry.spyOnAllFunctions(target);
|
||||
|
||||
expect(subject.spied1).toBe('I am a spy');
|
||||
expect(subject.spied2).toBe('I am a spy');
|
||||
expect(target.spied1).toBe('I am a spy');
|
||||
expect(target.spied2).toBe('I am a spy');
|
||||
expect(MyClass.prototype.spied2).toBe(noop2);
|
||||
});
|
||||
|
||||
it('does not override non-enumerable properties (like Object.prototype methods)', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = {
|
||||
const target = {
|
||||
spied1: function() {}
|
||||
};
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject);
|
||||
spyRegistry.spyOnAllFunctions(target);
|
||||
|
||||
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');
|
||||
expect(target.spied1).toBe('I am a spy');
|
||||
expect(target.toString).not.toBe('I am a spy');
|
||||
expect(target.hasOwnProperty).not.toBe('I am a spy');
|
||||
});
|
||||
describe('when includeNonEnumerable is true', function() {
|
||||
it('does not override Object.prototype methods', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = {
|
||||
const target = {
|
||||
spied1: function() {}
|
||||
};
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, 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');
|
||||
expect(target.spied1).toBe('I am a spy');
|
||||
expect(target.toString).not.toBe('I am a spy');
|
||||
expect(target.hasOwnProperty).not.toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('overrides non-enumerable properties', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = {
|
||||
const target = {
|
||||
spied1: function() {},
|
||||
spied2: function() {}
|
||||
};
|
||||
|
||||
Object.defineProperty(subject, 'spied2', {
|
||||
Object.defineProperty(target, 'spied2', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, true);
|
||||
|
||||
expect(subject.spied1).toBe('I am a spy');
|
||||
expect(subject.spied2).toBe('I am a spy');
|
||||
expect(target.spied1).toBe('I am a spy');
|
||||
expect(target.spied2).toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should not spy on non-enumerable functions named constructor', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = {
|
||||
const target = {
|
||||
constructor: function() {}
|
||||
};
|
||||
|
||||
Object.defineProperty(subject, 'constructor', {
|
||||
Object.defineProperty(target, 'constructor', {
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, true);
|
||||
|
||||
expect(subject.constructor).not.toBe('I am a spy');
|
||||
expect(target.constructor).not.toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should spy on enumerable functions named constructor', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = {
|
||||
const target = {
|
||||
constructor: function() {}
|
||||
};
|
||||
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, true);
|
||||
|
||||
expect(subject.constructor).toBe('I am a spy');
|
||||
expect(target.constructor).toBe('I am a spy');
|
||||
});
|
||||
|
||||
it('should not throw an exception if we try and access strict mode restricted properties', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subject = function() {};
|
||||
const target = function() {};
|
||||
const fn = function() {
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, true);
|
||||
};
|
||||
|
||||
expect(fn).not.toThrow();
|
||||
});
|
||||
|
||||
it('should not spy on properties which are more permissable further up the prototype chain', function() {
|
||||
const spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
const spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
createSpy: function() {
|
||||
return 'I am a spy';
|
||||
}
|
||||
});
|
||||
const subjectParent = Object.defineProperty({}, 'sharedProp', {
|
||||
const targetParent = Object.defineProperty({}, 'sharedProp', {
|
||||
value: function() {},
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
const subject = Object.create(subjectParent);
|
||||
const target = Object.create(targetParent);
|
||||
|
||||
Object.defineProperty(subject, 'sharedProp', {
|
||||
Object.defineProperty(target, 'sharedProp', {
|
||||
value: function() {}
|
||||
});
|
||||
|
||||
const fn = function() {
|
||||
spyRegistry.spyOnAllFunctions(subject, true);
|
||||
spyRegistry.spyOnAllFunctions(target, true);
|
||||
};
|
||||
|
||||
expect(fn).not.toThrow();
|
||||
expect(subject).not.toBe('I am a spy');
|
||||
expect(target).not.toBe('I am a spy');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -529,90 +565,90 @@ describe('SpyRegistry', function() {
|
||||
describe('#clearSpies', function() {
|
||||
it('restores the original functions on the spied-upon objects', function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subject = { spiedFunc: originalFunction };
|
||||
target = { spiedFunc: originalFunction };
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(subject.spiedFunc).toBe(originalFunction);
|
||||
expect(target.spiedFunc).toBe(originalFunction);
|
||||
});
|
||||
|
||||
it('restores the original functions, even when that spy has been replace and re-spied upon', function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subject = { spiedFunc: originalFunction };
|
||||
target = { spiedFunc: originalFunction };
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
|
||||
// replace the original spy with some other function
|
||||
subject.spiedFunc = function() {};
|
||||
target.spiedFunc = function() {};
|
||||
|
||||
// spy on the function in that location again
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(subject.spiedFunc).toBe(originalFunction);
|
||||
expect(target.spiedFunc).toBe(originalFunction);
|
||||
});
|
||||
|
||||
it("does not add a property that the spied-upon object didn't originally have", function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subjectParent = { spiedFunc: originalFunction };
|
||||
targetParent = { spiedFunc: originalFunction };
|
||||
|
||||
const subject = Object.create(subjectParent);
|
||||
const target = Object.create(targetParent);
|
||||
|
||||
expect(subject.hasOwnProperty('spiedFunc')).toBe(false);
|
||||
expect(target.hasOwnProperty('spiedFunc')).toBe(false);
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(subject.hasOwnProperty('spiedFunc')).toBe(false);
|
||||
expect(subject.spiedFunc).toBe(originalFunction);
|
||||
expect(target.hasOwnProperty('spiedFunc')).toBe(false);
|
||||
expect(target.spiedFunc).toBe(originalFunction);
|
||||
});
|
||||
|
||||
it("restores the original function when it's inherited and cannot be deleted", function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalFunction = function() {},
|
||||
subjectParent = { spiedFunc: originalFunction };
|
||||
targetParent = { spiedFunc: originalFunction };
|
||||
|
||||
const subject = Object.create(subjectParent);
|
||||
const target = Object.create(targetParent);
|
||||
|
||||
spyRegistry.spyOn(subject, 'spiedFunc');
|
||||
spyRegistry.spyOn(target, 'spiedFunc');
|
||||
|
||||
// simulate a spy that cannot be deleted
|
||||
Object.defineProperty(subject, 'spiedFunc', {
|
||||
Object.defineProperty(target, 'spiedFunc', {
|
||||
configurable: false
|
||||
});
|
||||
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(jasmineUnderTest.isSpy(subject.spiedFunc)).toBe(false);
|
||||
expect(jasmineUnderTest.isSpy(target.spiedFunc)).toBe(false);
|
||||
});
|
||||
|
||||
it('restores window.onerror by overwriting, not deleting', function() {
|
||||
@@ -621,7 +657,7 @@ describe('SpyRegistry', function() {
|
||||
|
||||
const spies = [],
|
||||
global = new FakeWindow(),
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
@@ -639,55 +675,55 @@ describe('SpyRegistry', function() {
|
||||
describe('spying on properties', function() {
|
||||
it('restores the original properties on the spied-upon objects', function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalReturn = 1,
|
||||
subject = {};
|
||||
target = {};
|
||||
|
||||
Object.defineProperty(subject, 'spiedProp', {
|
||||
Object.defineProperty(target, 'spiedProp', {
|
||||
get: function() {
|
||||
return originalReturn;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(subject.spiedProp).toBe(originalReturn);
|
||||
expect(target.spiedProp).toBe(originalReturn);
|
||||
});
|
||||
|
||||
it("does not add a property that the spied-upon object didn't originally have", function() {
|
||||
const spies = [],
|
||||
spyRegistry = new jasmineUnderTest.SpyRegistry({
|
||||
spyRegistry = new privateUnderTest.SpyRegistry({
|
||||
currentSpies: function() {
|
||||
return spies;
|
||||
},
|
||||
createSpy: createSpy
|
||||
}),
|
||||
originalReturn = 1,
|
||||
subjectParent = {};
|
||||
targetParent = {};
|
||||
|
||||
Object.defineProperty(subjectParent, 'spiedProp', {
|
||||
Object.defineProperty(targetParent, 'spiedProp', {
|
||||
get: function() {
|
||||
return originalReturn;
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
|
||||
const subject = Object.create(subjectParent);
|
||||
const target = Object.create(targetParent);
|
||||
|
||||
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
|
||||
expect(target.hasOwnProperty('spiedProp')).toBe(false);
|
||||
|
||||
spyRegistry.spyOnProperty(subject, 'spiedProp');
|
||||
spyRegistry.spyOnProperty(target, 'spiedProp');
|
||||
spyRegistry.clearSpies();
|
||||
|
||||
expect(subject.hasOwnProperty('spiedProp')).toBe(false);
|
||||
expect(subject.spiedProp).toBe(originalReturn);
|
||||
expect(target.hasOwnProperty('spiedProp')).toBe(false);
|
||||
expect(target.spiedProp).toBe(originalReturn);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ describe('Spies', function() {
|
||||
let env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env = new privateUnderTest.Env();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -50,8 +50,8 @@ describe('Spies', function() {
|
||||
TestClass.prototype.someFunction
|
||||
);
|
||||
|
||||
expect(spy.and).toEqual(jasmine.any(jasmineUnderTest.SpyStrategy));
|
||||
expect(spy.calls).toEqual(jasmine.any(jasmineUnderTest.CallTracker));
|
||||
expect(spy.and).toEqual(jasmine.any(privateUnderTest.SpyStrategy));
|
||||
expect(spy.calls).toEqual(jasmine.any(privateUnderTest.CallTracker));
|
||||
});
|
||||
|
||||
it('tracks the argument of calls', function() {
|
||||
@@ -97,17 +97,11 @@ describe('Spies', function() {
|
||||
it('preserves arity of original function', function() {
|
||||
const functions = [
|
||||
function nullary() {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function unary(arg) {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function binary(arg1, arg2) {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function ternary(arg1, arg2, arg3) {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function quaternary(arg1, arg2, arg3, arg4) {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function quinary(arg1, arg2, arg3, arg4, arg5) {},
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function senary(arg1, arg2, arg3, arg4, arg5, arg6) {}
|
||||
];
|
||||
|
||||
@@ -159,7 +153,7 @@ describe('Spies', function() {
|
||||
it('should throw if you do not pass an array or object argument', function() {
|
||||
expect(function() {
|
||||
env.createSpyObj('BaseName');
|
||||
}).toThrow(
|
||||
}).toThrowError(
|
||||
'createSpyObj requires a non-empty array or object of method names to create spies for'
|
||||
);
|
||||
});
|
||||
@@ -167,7 +161,7 @@ describe('Spies', function() {
|
||||
it('should throw if you pass an empty array argument', function() {
|
||||
expect(function() {
|
||||
env.createSpyObj('BaseName', []);
|
||||
}).toThrow(
|
||||
}).toThrowError(
|
||||
'createSpyObj requires a non-empty array or object of method names to create spies for'
|
||||
);
|
||||
});
|
||||
@@ -175,7 +169,7 @@ describe('Spies', function() {
|
||||
it('should throw if you pass an empty object argument', function() {
|
||||
expect(function() {
|
||||
env.createSpyObj('BaseName', {});
|
||||
}).toThrow(
|
||||
}).toThrowError(
|
||||
'createSpyObj requires a non-empty array or object of method names to create spies for'
|
||||
);
|
||||
});
|
||||
@@ -247,7 +241,7 @@ describe('Spies', function() {
|
||||
});
|
||||
|
||||
it('uses the provided matchersUtil selecting a strategy', function() {
|
||||
const matchersUtil = new jasmineUnderTest.MatchersUtil({
|
||||
const matchersUtil = new privateUnderTest.MatchersUtil({
|
||||
customTesters: [
|
||||
function(a, b) {
|
||||
if ((a === 'bar' && b === 'baz') || (a === 'baz' && b === 'bar')) {
|
||||
@@ -256,7 +250,7 @@ describe('Spies', function() {
|
||||
}
|
||||
]
|
||||
});
|
||||
const spy = new jasmineUnderTest.Spy('aSpy', matchersUtil);
|
||||
const spy = new privateUnderTest.Spy('aSpy', matchersUtil);
|
||||
spy.and.returnValue('default strategy return value');
|
||||
spy.withArgs('bar').and.returnValue('custom strategy return value');
|
||||
expect(spy('foo')).toEqual('default strategy return value');
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
describe('SpyStrategy', function() {
|
||||
it('defaults its name to unknown', function() {
|
||||
const spyStrategy = new jasmineUnderTest.SpyStrategy();
|
||||
const spyStrategy = new privateUnderTest.SpyStrategy();
|
||||
|
||||
expect(spyStrategy.identity).toEqual('unknown');
|
||||
});
|
||||
|
||||
it('takes a name', function() {
|
||||
const spyStrategy = new jasmineUnderTest.SpyStrategy({ name: 'foo' });
|
||||
const spyStrategy = new privateUnderTest.SpyStrategy({ name: 'foo' });
|
||||
|
||||
expect(spyStrategy.identity).toEqual('foo');
|
||||
});
|
||||
|
||||
it('stubs an original function, if provided', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.exec();
|
||||
|
||||
@@ -22,7 +22,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it("allows an original function to be called, passed through the params and returns it's value", function() {
|
||||
const originalFn = jasmine.createSpy('original').and.returnValue(42),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.callThrough();
|
||||
const returnValue = spyStrategy.exec(null, ['foo']);
|
||||
@@ -34,7 +34,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('can return a specified value when executed', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.returnValue(17);
|
||||
const returnValue = spyStrategy.exec();
|
||||
@@ -45,7 +45,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('can return specified values in order specified when executed', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.returnValues('value1', 'value2', 'value3');
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows an exception to be thrown when executed', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.throwError(new TypeError('bar'));
|
||||
|
||||
@@ -70,7 +70,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows a string to be thrown, wrapping it into an exception when executed', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.throwError('bar');
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows a non-Error to be thrown when executed', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.throwError({ code: 'ESRCH' });
|
||||
|
||||
@@ -95,7 +95,7 @@ describe('SpyStrategy', function() {
|
||||
it('allows a fake function to be called instead', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
fakeFn = jasmine.createSpy('fake').and.returnValue(67),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.callFake(fakeFn);
|
||||
const returnValue = spyStrategy.exec();
|
||||
@@ -106,10 +106,10 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows a fake async function to be called instead', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
fakeFn = jasmine
|
||||
.createSpy('fake')
|
||||
.and.callFake(eval('async () => { return 67; }')),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
fakeFn = jasmine.createSpy('fake').and.callFake(async () => {
|
||||
return 67;
|
||||
}),
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.callFake(fakeFn);
|
||||
spyStrategy
|
||||
@@ -128,7 +128,7 @@ describe('SpyStrategy', function() {
|
||||
describe('#resolveTo', function() {
|
||||
it('allows a resolved promise to be returned', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn
|
||||
});
|
||||
|
||||
@@ -144,7 +144,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows an empty resolved promise to be returned', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn
|
||||
});
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('SpyStrategy', function() {
|
||||
describe('#rejectWith', function() {
|
||||
it('allows a rejected promise to be returned', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn
|
||||
});
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows an empty rejected promise to be returned', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn
|
||||
});
|
||||
|
||||
@@ -196,7 +196,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it('allows a non-Error to be rejected', function(done) {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn
|
||||
});
|
||||
|
||||
@@ -220,7 +220,7 @@ describe('SpyStrategy', function() {
|
||||
.createSpy('custom strategy')
|
||||
.and.returnValue(plan),
|
||||
originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn,
|
||||
customStrategies: {
|
||||
doSomething: customStrategy
|
||||
@@ -237,7 +237,7 @@ describe('SpyStrategy', function() {
|
||||
|
||||
it("throws an error if a custom strategy doesn't return a function", function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: originalFn,
|
||||
customStrategies: {
|
||||
doSomething: function() {
|
||||
@@ -252,37 +252,32 @@ describe('SpyStrategy', function() {
|
||||
});
|
||||
|
||||
it('does not allow custom strategies to overwrite existing methods', function() {
|
||||
const spyStrategy = new jasmineUnderTest.SpyStrategy({
|
||||
const spyStrategy = new privateUnderTest.SpyStrategy({
|
||||
fn: function() {},
|
||||
customStrategies: {
|
||||
exec: function() {}
|
||||
}
|
||||
});
|
||||
|
||||
expect(spyStrategy.exec).toBe(jasmineUnderTest.SpyStrategy.prototype.exec);
|
||||
expect(spyStrategy.exec).toBe(privateUnderTest.SpyStrategy.prototype.exec);
|
||||
});
|
||||
|
||||
it('throws an error when a non-function is passed to callFake strategy', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyOn(jasmineUnderTest, 'isFunction_').and.returnValue(false);
|
||||
spyOn(jasmineUnderTest, 'isAsyncFunction_').and.returnValue(false);
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
expect(function() {
|
||||
spyStrategy.callFake(function() {});
|
||||
}).toThrowError(/^Argument passed to callFake should be a function, got/);
|
||||
|
||||
expect(function() {
|
||||
spyStrategy.callFake(function() {});
|
||||
}).toThrowError(/^Argument passed to callFake should be a function, got/);
|
||||
spyStrategy.callFake('not a function');
|
||||
}).toThrowError(
|
||||
'Argument passed to callFake should be a function, got not a function'
|
||||
);
|
||||
});
|
||||
|
||||
it('allows generator functions to be passed to callFake strategy', function() {
|
||||
const generator = function*() {
|
||||
yield 'ok';
|
||||
},
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: function() {} });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: function() {} });
|
||||
|
||||
spyStrategy.callFake(generator);
|
||||
|
||||
@@ -292,7 +287,7 @@ describe('SpyStrategy', function() {
|
||||
it('allows a return to plan stubbing after another strategy', function() {
|
||||
const originalFn = jasmine.createSpy('original'),
|
||||
fakeFn = jasmine.createSpy('fake').and.returnValue(67),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ fn: originalFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ fn: originalFn });
|
||||
|
||||
spyStrategy.callFake(fakeFn);
|
||||
let returnValue = spyStrategy.exec();
|
||||
@@ -309,7 +304,7 @@ describe('SpyStrategy', function() {
|
||||
it('returns the spy after changing the strategy', function() {
|
||||
const spy = {},
|
||||
spyFn = jasmine.createSpy('spyFn').and.returnValue(spy),
|
||||
spyStrategy = new jasmineUnderTest.SpyStrategy({ getSpy: spyFn });
|
||||
spyStrategy = new privateUnderTest.SpyStrategy({ getSpy: spyFn });
|
||||
|
||||
expect(spyStrategy.callThrough()).toBe(spy);
|
||||
expect(spyStrategy.returnValue()).toBe(spy);
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('StackTrace', function() {
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||
};
|
||||
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toEqual('Error: nope');
|
||||
expect(result.style).toEqual('v8');
|
||||
@@ -39,7 +39,7 @@ describe('StackTrace', function() {
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||
};
|
||||
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toEqual('Error: line 1\nline 2');
|
||||
const rawFrames = result.frames.map(function(f) {
|
||||
@@ -51,6 +51,27 @@ describe('StackTrace', function() {
|
||||
]);
|
||||
});
|
||||
|
||||
it('understands Chrome/Edge style traces with messages containing blank lines', function() {
|
||||
const error = {
|
||||
message: 'line 1\n\nline 2',
|
||||
stack:
|
||||
'Error: line 1\n\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)'
|
||||
};
|
||||
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toEqual('Error: line 1\n\nline 2');
|
||||
const 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() {
|
||||
const error = {
|
||||
message: 'nope',
|
||||
@@ -61,7 +82,7 @@ describe('StackTrace', function() {
|
||||
' at Immediate.<anonymous> (/somewhere/jasmine/lib/jasmine-core/jasmine.js:4314:12)\n' +
|
||||
' at runCallback (timers.js:672:20)'
|
||||
};
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toEqual('Error');
|
||||
expect(result.style).toEqual('v8');
|
||||
@@ -95,14 +116,14 @@ describe('StackTrace', function() {
|
||||
]);
|
||||
});
|
||||
|
||||
it('understands Safari <=14/Firefox/Phantom-OS X style traces', function() {
|
||||
it('understands Safari <=14/Firefox style traces', function() {
|
||||
const error = {
|
||||
message: 'nope',
|
||||
stack:
|
||||
'http://localhost:8888/__spec__/core/UtilSpec.js:115:28\n' +
|
||||
'run@http://localhost:8888/__jasmine__/jasmine.js:4320:27'
|
||||
};
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toBeFalsy();
|
||||
expect(result.style).toEqual('webkit');
|
||||
@@ -129,7 +150,7 @@ describe('StackTrace', function() {
|
||||
'@http://localhost:8888/__spec__/core/FooSpec.js:164:24\n' +
|
||||
'attempt@http://localhost:8888/__jasmine__/jasmine.js:8074:44\n'
|
||||
};
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toBeFalsy();
|
||||
expect(result.style).toEqual('webkit');
|
||||
@@ -149,46 +170,16 @@ describe('StackTrace', function() {
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not mistake gibberish for Safari/Firefox/Phantom-OS X style traces', function() {
|
||||
it('does not mistake gibberish for Safari/Firefox style traces', function() {
|
||||
const error = {
|
||||
message: 'nope',
|
||||
stack: 'randomcharsnotincludingwhitespace'
|
||||
};
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
expect(result.style).toBeNull();
|
||||
expect(result.frames).toEqual([{ raw: error.stack }]);
|
||||
});
|
||||
|
||||
it('understands Phantom-Linux style traces', function() {
|
||||
const 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)'
|
||||
};
|
||||
|
||||
const 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() {
|
||||
const error = {
|
||||
message: 'nope',
|
||||
@@ -196,7 +187,7 @@ describe('StackTrace', function() {
|
||||
' at UserContext.<anonymous> (http://localhost:8888/__spec__/core/UtilSpec.js:115:19)\n'
|
||||
};
|
||||
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
@@ -218,7 +209,7 @@ describe('StackTrace', function() {
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||
};
|
||||
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
expect(result.style).toEqual('v8');
|
||||
expect(result.frames).toEqual([
|
||||
{
|
||||
@@ -241,7 +232,7 @@ describe('StackTrace', function() {
|
||||
]);
|
||||
});
|
||||
|
||||
it('consideres different types of errors', function() {
|
||||
it('considers different types of errors', function() {
|
||||
const error = {
|
||||
message: 'nope',
|
||||
stack:
|
||||
@@ -250,7 +241,7 @@ describe('StackTrace', function() {
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||
};
|
||||
|
||||
const result = new jasmineUnderTest.StackTrace(error);
|
||||
const result = new privateUnderTest.StackTrace(error);
|
||||
|
||||
expect(result.message).toEqual('TypeError: nope');
|
||||
expect(result.frames).toEqual([
|
||||
@@ -278,7 +269,7 @@ describe('StackTrace', function() {
|
||||
' at QueueRunner.run (http://localhost:8888/__jasmine__/jasmine.js:4320:20)'
|
||||
};
|
||||
|
||||
const result_no_error = new jasmineUnderTest.StackTrace(no_error);
|
||||
const result_no_error = new privateUnderTest.StackTrace(no_error);
|
||||
|
||||
expect(result_no_error.message).not.toEqual(jasmine.anything());
|
||||
});
|
||||
|
||||
390
spec/core/SuiteBuilderSpec.js
Normal file
390
spec/core/SuiteBuilderSpec.js
Normal file
@@ -0,0 +1,390 @@
|
||||
describe('SuiteBuilder', function() {
|
||||
beforeEach(function() {
|
||||
// Rethrow exceptions to ease debugging
|
||||
spyOn(privateUnderTest.Suite.prototype, 'handleException').and.callFake(
|
||||
function(e) {
|
||||
throw e;
|
||||
}
|
||||
);
|
||||
spyOn(privateUnderTest.Spec.prototype, 'handleException').and.callFake(
|
||||
function(e) {
|
||||
throw e;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('creates the top suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(suiteBuilder.topSuite).toBeInstanceOf(privateUnderTest.Suite);
|
||||
expect(suiteBuilder.topSuite.description).toEqual(
|
||||
'Jasmine__TopLevel__Suite'
|
||||
);
|
||||
expect(suiteBuilder.topSuite.parentSuite).toBeUndefined();
|
||||
});
|
||||
|
||||
describe('#describe', function() {
|
||||
definesSuites('describe');
|
||||
});
|
||||
|
||||
describe('#fdescribe', function() {
|
||||
definesSuites('fdescribe');
|
||||
|
||||
it('focuses the suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
const suite = suiteBuilder.fdescribe('a suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
|
||||
expect(suite.isFocused).toBeTrue();
|
||||
expect(suiteBuilder.focusedRunables).toEqual([suite.id]);
|
||||
});
|
||||
|
||||
it('unfocuses any focused ancestor suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
const grandparent = suiteBuilder.fdescribe('a suite', function() {
|
||||
suiteBuilder.describe('another suite', function() {
|
||||
suiteBuilder.fdescribe('the focused suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
expect(suiteBuilder.focusedRunables).not.toContain(grandparent.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#xdescribe', function() {
|
||||
definesSuites('xdescribe');
|
||||
|
||||
it('excludes the suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
const suite = suiteBuilder.xdescribe('a suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
|
||||
expect(suite.markedExcluding).toBeTrue();
|
||||
});
|
||||
|
||||
it('causes child suites to be marked excluded', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
let suite;
|
||||
suiteBuilder.xdescribe('a suite', function() {
|
||||
suite = suiteBuilder.describe('another suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
|
||||
expect(suite.markedExcluding).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#it', function() {
|
||||
definesSpecs('it');
|
||||
});
|
||||
|
||||
describe('#fit', function() {
|
||||
definesSpecs('fit');
|
||||
});
|
||||
|
||||
describe('#xit', function() {
|
||||
definesSpecs('xit');
|
||||
});
|
||||
|
||||
function definesSuites(fnName) {
|
||||
it('links suites to their parents and children', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
let child;
|
||||
const parent = suiteBuilder[fnName]('parent', function() {
|
||||
child = suiteBuilder[fnName]('child', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
|
||||
expect(suiteBuilder.topSuite.children).toEqual([sameInstanceAs(parent)]);
|
||||
expect(parent.children).toEqual([sameInstanceAs(child)]);
|
||||
expect(child.parentSuite).toBe(parent);
|
||||
expect(parent.parentSuite).toBe(suiteBuilder.topSuite);
|
||||
});
|
||||
|
||||
it('gives each suite a unique ID', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
let child;
|
||||
const parent = suiteBuilder[fnName]('parent', function() {
|
||||
child = suiteBuilder[fnName]('child', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
|
||||
const ids = [suiteBuilder.topSuite.id, parent.id, child.id];
|
||||
|
||||
for (const id of ids) {
|
||||
expect(id).toMatch(/^suite[0-9]$/);
|
||||
}
|
||||
|
||||
expect(new Set(ids).size).toEqual(3);
|
||||
});
|
||||
}
|
||||
|
||||
function definesSpecs(fnName) {
|
||||
it('adds the spec to its suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
let spec;
|
||||
const suite = suiteBuilder.describe('a suite', function() {
|
||||
spec = suiteBuilder[fnName]('a spec', function() {});
|
||||
});
|
||||
|
||||
expect(suite.children).toEqual([sameInstanceAs(spec)]);
|
||||
});
|
||||
|
||||
it('gives each spec a unique ID', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
const spec1 = suiteBuilder[fnName]('a spec', function() {});
|
||||
const spec2 = suiteBuilder[fnName]('another spec', function() {});
|
||||
|
||||
expect(spec1.id).toMatch(/^spec[0-9]+$/);
|
||||
expect(spec2.id).toMatch(/^spec[0-9]+$/);
|
||||
expect(spec1.id).not.toEqual(spec2.id);
|
||||
});
|
||||
|
||||
it('gives each spec a full path', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
let spec;
|
||||
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.describe('a nested suite', function() {
|
||||
spec = suiteBuilder[fnName]('a spec', function() {});
|
||||
});
|
||||
});
|
||||
|
||||
expect(spec.getPath()).toEqual(['a suite', 'a nested suite', 'a spec']);
|
||||
});
|
||||
}
|
||||
|
||||
function sameInstanceAs(expected) {
|
||||
return {
|
||||
asymmetricMatch: function(actual) {
|
||||
return actual === expected;
|
||||
},
|
||||
jasmineToString: function(pp) {
|
||||
return '<same instance as ' + pp(expected) + '>';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
describe('Duplicate name handling', function() {
|
||||
describe('When forbidDuplicateNames is true', function() {
|
||||
let env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = { configuration: () => ({ forbidDuplicateNames: true }) };
|
||||
});
|
||||
|
||||
it('forbids duplicate spec names', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.describe('a nested suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
}).toThrowError(
|
||||
'Duplicate spec name "a spec" found in "a suite a nested suite"'
|
||||
);
|
||||
});
|
||||
|
||||
it('forbids duplicate spec names in the top suite', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.it('another spec');
|
||||
suiteBuilder.it('another spec');
|
||||
}).toThrowError(
|
||||
'Duplicate spec name "another spec" found in top suite'
|
||||
);
|
||||
});
|
||||
|
||||
it('forbids duplicate suite names', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.describe('a nested suite', function() {
|
||||
suiteBuilder.describe('another suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
suiteBuilder.describe('another suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
}).toThrowError(
|
||||
'Duplicate suite name "another suite" found in "a suite a nested suite"'
|
||||
);
|
||||
});
|
||||
|
||||
it('forbids duplicate suite names in the top suite', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.it('a spec');
|
||||
});
|
||||
}).toThrowError('Duplicate suite name "a suite" found in top suite');
|
||||
});
|
||||
|
||||
it('allows spec and suite names to be duplicated in different suites', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.describe('suite a', function() {
|
||||
suiteBuilder.describe('dupe suite', function() {
|
||||
suiteBuilder.it('dupe spec');
|
||||
suiteBuilder.describe('child suite', function() {
|
||||
suiteBuilder.it('dupe spec');
|
||||
});
|
||||
});
|
||||
});
|
||||
suiteBuilder.describe('suite b', function() {
|
||||
suiteBuilder.describe('dupe suite', function() {
|
||||
suiteBuilder.it('dupe spec');
|
||||
});
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('When forbidDuplicateNames is false', function() {
|
||||
let env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = { configuration: () => ({ forbidDuplicateNames: false }) };
|
||||
});
|
||||
|
||||
it('allows duplicate spec and suite names', function() {
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
expect(function() {
|
||||
suiteBuilder.describe('dupe suite', function() {
|
||||
suiteBuilder.it('dupe spec');
|
||||
suiteBuilder.it('dupe spec');
|
||||
});
|
||||
suiteBuilder.describe('dupe suite', function() {
|
||||
suiteBuilder.it('dupe spec');
|
||||
suiteBuilder.it('dupe spec');
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#parallelReset', function() {
|
||||
it('resets the top suite result', function() {
|
||||
privateUnderTest.Suite.prototype.handleException.and.callThrough();
|
||||
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
suiteBuilder.topSuite.handleException(new Error('nope'));
|
||||
suiteBuilder.parallelReset();
|
||||
|
||||
expect(suiteBuilder.topSuite.result).toEqual({
|
||||
id: suiteBuilder.topSuite.id,
|
||||
description: 'Jasmine__TopLevel__Suite',
|
||||
fullName: '',
|
||||
failedExpectations: [],
|
||||
deprecationWarnings: [],
|
||||
duration: null,
|
||||
properties: null,
|
||||
parentSuiteId: null,
|
||||
filename: undefined
|
||||
});
|
||||
});
|
||||
|
||||
it('removes children of the top suite', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
suiteBuilder.describe('a suite', function() {
|
||||
suiteBuilder.it('a nested spec');
|
||||
});
|
||||
suiteBuilder.it('a spec');
|
||||
|
||||
suiteBuilder.parallelReset();
|
||||
|
||||
expect(suiteBuilder.topSuite.children).toEqual([]);
|
||||
});
|
||||
|
||||
it('preserves top suite befores and afters', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
|
||||
function beforeAll() {}
|
||||
function beforeEach() {}
|
||||
function afterEach() {}
|
||||
function afterAll() {}
|
||||
|
||||
suiteBuilder.beforeAll(beforeAll);
|
||||
suiteBuilder.beforeEach(beforeEach);
|
||||
suiteBuilder.afterEach(afterEach);
|
||||
suiteBuilder.afterAll(afterAll);
|
||||
|
||||
suiteBuilder.parallelReset();
|
||||
|
||||
expect(suiteBuilder.topSuite.beforeAllFns).toEqual([
|
||||
jasmine.objectContaining({ fn: beforeAll })
|
||||
]);
|
||||
expect(suiteBuilder.topSuite.beforeFns).toEqual([
|
||||
jasmine.objectContaining({ fn: beforeEach })
|
||||
]);
|
||||
expect(suiteBuilder.topSuite.afterFns).toEqual([
|
||||
jasmine.objectContaining({ fn: afterEach })
|
||||
]);
|
||||
expect(suiteBuilder.topSuite.afterAllFns).toEqual([
|
||||
jasmine.objectContaining({ fn: afterAll })
|
||||
]);
|
||||
});
|
||||
|
||||
it('resets totalSpecsDefined', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
suiteBuilder.it('a spec');
|
||||
|
||||
suiteBuilder.parallelReset();
|
||||
|
||||
expect(suiteBuilder.totalSpecsDefined).toEqual(0);
|
||||
});
|
||||
|
||||
it('resets focusedRunables', function() {
|
||||
const env = { configuration: () => ({}) };
|
||||
const suiteBuilder = new privateUnderTest.SuiteBuilder({ env });
|
||||
suiteBuilder.fit('a spec', function() {});
|
||||
|
||||
suiteBuilder.parallelReset();
|
||||
|
||||
expect(suiteBuilder.focusedRunables).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -2,7 +2,7 @@ describe('Suite', function() {
|
||||
let env;
|
||||
|
||||
beforeEach(function() {
|
||||
env = new jasmineUnderTest.Env();
|
||||
env = new privateUnderTest.Env();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@@ -10,7 +10,7 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('keeps its id', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
id: 456,
|
||||
description: 'I am a suite'
|
||||
@@ -20,7 +20,7 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('returns blank full name for top level suite', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite'
|
||||
});
|
||||
@@ -29,12 +29,12 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('returns its full name when it has parent suites', function() {
|
||||
const parentSuite = new jasmineUnderTest.Suite({
|
||||
const parentSuite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a parent suite',
|
||||
parentSuite: jasmine.createSpy('pretend top level suite')
|
||||
}),
|
||||
suite = new jasmineUnderTest.Suite({
|
||||
suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite',
|
||||
parentSuite: parentSuite
|
||||
@@ -44,7 +44,7 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('adds beforeEach functions in order of needed execution', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite'
|
||||
}),
|
||||
@@ -61,7 +61,7 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('adds beforeAll functions in order of needed execution', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite'
|
||||
}),
|
||||
@@ -71,25 +71,14 @@ describe('Suite', function() {
|
||||
suite.beforeAll(outerBefore);
|
||||
suite.beforeAll(innerBefore);
|
||||
|
||||
function sameInstance(expected) {
|
||||
return {
|
||||
asymmetricMatch: function(actual) {
|
||||
return actual === expected;
|
||||
},
|
||||
jasmineToString: function() {
|
||||
return `<same instance as ${expected}>`;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
expect(suite.beforeAllFns).toEqual([
|
||||
{ fn: outerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) },
|
||||
{ fn: innerBefore.fn, type: 'beforeAll', suite: sameInstance(suite) }
|
||||
{ fn: outerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) },
|
||||
{ fn: innerBefore.fn, type: 'beforeAll', suite: jasmine.is(suite) }
|
||||
]);
|
||||
});
|
||||
|
||||
it('adds afterEach functions in order of needed execution', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite'
|
||||
}),
|
||||
@@ -106,7 +95,7 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('adds afterAll functions in order of needed execution', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
description: 'I am a suite'
|
||||
}),
|
||||
@@ -123,55 +112,135 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('has a status of failed if any expectations have failed', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function() {
|
||||
return 'hi';
|
||||
}
|
||||
});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
|
||||
suite.addExpectationResult(false);
|
||||
expect(suite.status()).toBe('failed');
|
||||
suite.addExpectationResult(false, {});
|
||||
expect(suite.getResult().status).toBe('failed');
|
||||
});
|
||||
|
||||
it('retrieves a result with updated status', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
|
||||
expect(suite.getResult().status).toBe('passed');
|
||||
});
|
||||
|
||||
it('retrieves a result with pending status', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
suite.pend();
|
||||
|
||||
expect(suite.getResult().status).toBe('pending');
|
||||
});
|
||||
|
||||
it('throws an ExpectationFailed when receiving a failed expectation when throwOnExpectationFailure is set', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function(data) {
|
||||
return data;
|
||||
},
|
||||
const suite = new privateUnderTest.Suite({
|
||||
throwOnExpectationFailure: true
|
||||
});
|
||||
|
||||
expect(function() {
|
||||
suite.addExpectationResult(false, 'failed');
|
||||
}).toThrowError(jasmineUnderTest.errors.ExpectationFailed);
|
||||
suite.addExpectationResult(false, { message: 'failed' });
|
||||
}).toThrowError(jasmineUnderTest.private.errors.ExpectationFailed);
|
||||
|
||||
expect(suite.status()).toBe('failed');
|
||||
expect(suite.result.failedExpectations).toEqual(['failed']);
|
||||
expect(suite.getResult().status).toBe('failed');
|
||||
expect(suite.result.failedExpectations).toEqual([
|
||||
jasmine.objectContaining({ message: 'failed' })
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not add an additional failure when an expectation fails', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
|
||||
suite.onException(new jasmineUnderTest.errors.ExpectationFailed());
|
||||
suite.handleException(
|
||||
new jasmineUnderTest.private.errors.ExpectationFailed()
|
||||
);
|
||||
|
||||
expect(suite.getResult().failedExpectations).toEqual([]);
|
||||
});
|
||||
|
||||
it('forwards late expectation failures to onLateError', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new privateUnderTest.Suite({ onLateError });
|
||||
const data = {
|
||||
matcherName: '',
|
||||
passed: false,
|
||||
expected: '',
|
||||
actual: '',
|
||||
error: new Error('nope')
|
||||
};
|
||||
|
||||
suite.reportedDone = true;
|
||||
suite.addExpectationResult(false, data, true);
|
||||
|
||||
expect(onLateError).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^Error: nope/)
|
||||
})
|
||||
);
|
||||
expect(suite.result.failedExpectations).toEqual([]);
|
||||
});
|
||||
|
||||
it('does not forward non-late expectation failures to onLateError', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new privateUnderTest.Suite({
|
||||
onLateError
|
||||
});
|
||||
const data = {
|
||||
matcherName: '',
|
||||
passed: false,
|
||||
expected: '',
|
||||
actual: '',
|
||||
error: new Error('nope')
|
||||
};
|
||||
|
||||
suite.addExpectationResult(false, data, true);
|
||||
|
||||
expect(onLateError).not.toHaveBeenCalled();
|
||||
expect(suite.result.failedExpectations.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('forwards late handleException calls to onLateError', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new privateUnderTest.Suite({
|
||||
onLateError
|
||||
});
|
||||
const error = new Error('oops');
|
||||
|
||||
suite.reportedDone = true;
|
||||
suite.handleException(error);
|
||||
|
||||
expect(onLateError).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
message: jasmine.stringMatching(/^Error: oops/)
|
||||
})
|
||||
);
|
||||
expect(suite.result.failedExpectations).toEqual([]);
|
||||
});
|
||||
|
||||
it('does not forward non-late handleException calls to onLateError', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new privateUnderTest.Suite({
|
||||
onLateError
|
||||
});
|
||||
const error = new Error('oops');
|
||||
|
||||
suite.handleException(error);
|
||||
|
||||
expect(onLateError).not.toHaveBeenCalled();
|
||||
expect(suite.result.failedExpectations.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('clears the reportedDone flag when reset', function() {
|
||||
const suite = new privateUnderTest.Suite({
|
||||
queueableFn: { fn: function() {} }
|
||||
});
|
||||
suite.reportedDone = true;
|
||||
|
||||
suite.reset();
|
||||
|
||||
expect(suite.reportedDone).toBeFalse();
|
||||
});
|
||||
|
||||
it('calls timer to compute duration', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
env: env,
|
||||
id: 456,
|
||||
description: 'I am a suite',
|
||||
@@ -184,19 +253,19 @@ describe('Suite', function() {
|
||||
|
||||
describe('#sharedUserContext', function() {
|
||||
beforeEach(function() {
|
||||
this.suite = new jasmineUnderTest.Suite({});
|
||||
this.suite = new privateUnderTest.Suite({});
|
||||
});
|
||||
|
||||
it('returns a UserContext', function() {
|
||||
expect(this.suite.sharedUserContext().constructor).toBe(
|
||||
jasmineUnderTest.UserContext
|
||||
privateUnderTest.UserContext
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('attr.autoCleanClosures', function() {
|
||||
function arrangeSuite(attrs) {
|
||||
const suite = new jasmineUnderTest.Suite(attrs);
|
||||
const suite = new privateUnderTest.Suite(attrs);
|
||||
suite.beforeAll(function() {});
|
||||
suite.beforeEach(function() {});
|
||||
suite.afterEach(function() {});
|
||||
@@ -234,21 +303,21 @@ describe('Suite', function() {
|
||||
|
||||
describe('#reset', function() {
|
||||
it('should reset the "pending" status', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
suite.pend();
|
||||
suite.reset();
|
||||
expect(suite.getResult().status).toBe('passed');
|
||||
});
|
||||
|
||||
it('should not reset the "pending" status when the suite was excluded', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
suite.exclude();
|
||||
suite.reset();
|
||||
expect(suite.getResult().status).toBe('pending');
|
||||
});
|
||||
|
||||
it('should also reset the children', function() {
|
||||
const suite = new jasmineUnderTest.Suite({});
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
const child1 = jasmine.createSpyObj(['reset']);
|
||||
const child2 = jasmine.createSpyObj(['reset']);
|
||||
suite.addChild(child1);
|
||||
@@ -261,12 +330,8 @@ describe('Suite', function() {
|
||||
});
|
||||
|
||||
it('should reset the failedExpectations', function() {
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
expectationResultFactory: function(error) {
|
||||
return error;
|
||||
}
|
||||
});
|
||||
suite.onException(new Error());
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
suite.handleException(new Error());
|
||||
|
||||
suite.reset();
|
||||
|
||||
@@ -279,7 +344,7 @@ describe('Suite', function() {
|
||||
describe('#onMultipleDone', function() {
|
||||
it('reports a special error when it is the top suite', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
onLateError,
|
||||
parentSuite: null
|
||||
});
|
||||
@@ -296,7 +361,7 @@ describe('Suite', function() {
|
||||
|
||||
it('reports an error including the suite name when it is a normal suite', function() {
|
||||
const onLateError = jasmine.createSpy('onLateError');
|
||||
const suite = new jasmineUnderTest.Suite({
|
||||
const suite = new privateUnderTest.Suite({
|
||||
onLateError,
|
||||
description: 'the suite',
|
||||
parentSuite: {
|
||||
@@ -315,4 +380,49 @@ describe('Suite', function() {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#hasChildWithDescription', function() {
|
||||
it('returns true if there is a child with the given description', function() {
|
||||
const subject = new privateUnderTest.Suite({});
|
||||
const description = 'a spec';
|
||||
subject.addChild({ description });
|
||||
|
||||
expect(subject.hasChildWithDescription(description)).toBeTrue();
|
||||
});
|
||||
|
||||
it('returns false if there is no child with the given description', function() {
|
||||
const subject = new privateUnderTest.Suite({});
|
||||
subject.addChild({ description: 'a different spec' });
|
||||
|
||||
expect(subject.hasChildWithDescription('a spec')).toBeFalse();
|
||||
});
|
||||
|
||||
it('does not recurse into child suites', function() {
|
||||
const subject = new privateUnderTest.Suite({});
|
||||
const childSuite = new privateUnderTest.Suite({});
|
||||
subject.addChild(childSuite);
|
||||
const description = 'a spec';
|
||||
childSuite.addChild(description);
|
||||
|
||||
expect(subject.hasChildWithDescription('a spec')).toBeFalse();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setSuiteProperty', function() {
|
||||
it('throws if the key is not structured-cloneable', function() {
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
|
||||
expect(function() {
|
||||
suite.setSuiteProperty(new Promise(() => {}), '');
|
||||
}).toThrowError("Key can't be cloned");
|
||||
});
|
||||
|
||||
it('throws if the value is not structured-cloneable', function() {
|
||||
const suite = new privateUnderTest.Suite({});
|
||||
|
||||
expect(function() {
|
||||
suite.setSuiteProperty('k', new Promise(() => {}));
|
||||
}).toThrowError("Value can't be cloned");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user